Link to home
Start Free TrialLog in
Avatar of dennismv
dennismv

asked on

start arrays at 0 or 1

0 or 1 is the question.

Arrays in C++ start at 0.

However, sometimes it is more convenient to start them at 1.
For example, if I am to model a chess board as an array, I feel it is more convenient to number rows and columns between 1 and 8, rather than between 0 and 7.

If I have 3 items of something, I'd rather count them 1,2,3, instead of 0,1,2.

Hence, the question:  is this a matter of taste, or are there practical ways when you do need to use 0, or to use 1.

Just to note:  there are some things that are a matter of taste, but then someone comes up with a good reason to use one of those things and not the others.  That's why I'm asking.

If I get a really good reason or a really good reply, I will increase points before awarding points.
SOLUTION
Avatar of esorf
esorf

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dennismv
dennismv

ASKER

hmm that's pretty good
Actually, I didn't expect this kind of reply.
It puts 0-based and 1-based together in a way that is a win-win situation -- no wasted space since you don't ignore array[0] and base 1 if you're into that.


ASKER CERTIFIED SOLUTION
Avatar of Axter
Axter
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I agree whole-heartedly with Axter on this one.  Learn to be comfortable with 0-based arrays -- don't try to create work-arounds for features that are built into the language.  This is just asking for a maintenance nightmare!.

-Keith
Ok

well is there a reason as to why 0-based convention for arrays was picked ?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
If arrays started at 1, then 0 would be out of bounds. If I mistyped 0 somewhere, I'd have a memory corruption. If arrays start at 0 however, then I have to mistype -1 in order to corrupt it. Starting arrays at 0 would seem to decrease the chance of a memory error off of a typo on the index. Also, if an index were used to traverse the array, the index could not be used to the full extent of its size. There would be 2^(sizeof(T)*8) - 1 possible objects, as opposed to 2^(sizeof(T)*8).
At the lowest level, the compiler needs to come up with an address for an indexed array reference.  The array is the base address and then the byte offset from that to get to the Nth element is
   offset = sizeof(T) * index
if I have a 1 based array and I don't want to allocate and not use the first element, my offset calculation has to be
   offset = sizeof(T) * (index - 1)

That subtraction in every array reference makes 1 based arrays more expensive.  So you spend either space or time using 1 based arrays.  That's why most languages use 0 based arrays.

With respect to kledbetter's comment, I respectfully disagree about the need to "get used to it".  As I stated in my initial post, 0 basedness is a fact of the language.  But that doesn't mean I shouldn't use classes to allow me to express my program in terms of the domain data model.  

For example, Excel sheets start with Row 1.  Users are comfortable with this.  The fact that the app is written in C++ shouldn't require that users change their model of a spreadsheet.  So at some point in the Excel implementation there is a mapping from the user's numbering of rows to the applications data storage model.  I think there's a lot of +1 and -1 going on translating between storage model and user model.  And I suspect that the developers have hidden that within a class representation so that they don't have to be worrying about it throughout their application.  You can have your cake (domain model representation) while still working with the rules of the language.

- Frank
thanks

Ok, I see, on the low level we are working with bits.
If we want all 65536 values, we better do 0...65535
Anything larger will overflow.


About mistyping the index, I don't think mistyping is a big problem.  If it was known fact that arrays start at 1, then these mistypes would be rare.
>>But that doesn't mean I shouldn't use classes to allow me to express my program in terms of the domain data model.  

It means (in general) it's a bad idea to create classes that do not use the same paradigm as the language.
You're adding ambiguity to the code, which will make it harder to debug, and easier to introduce new bugs.

This is a bad idea all around.
There's very little upside, and a lot of downside to this approach.

If you use this approach, you would have to mix and match zero based logic with one based logic.
Or you would have to create classes for every object you used in your code.
That would mean you would have to create your own std::string, std::vector, std::iostream.
You would also have to replace many of the C-Standard-Functions which are zero based.

If you're not willing to replace all these objects and C-Functions, then you're going to have complex code mixing one based objects with zero based objects/functions.
I agree that it would be a monumental waste of time to recreate standard libraries to be 1 based.  There's no point.  That's because the domain of class string is C++ programming.  And we're all used to 0 based data types so we should stick with that as domain appropriate.

However, you should create application class interfaces that reflect the domain of the application, not the language.  If I'm writing Excel and we talk about Row 1 on screen, I should be able to continue talking about Row 1 in the code.
Besides memory addressing, in the past, I wondered so much about using 0-based array in C++ because in some programs I think it's better to use 1-based array. Later I found out that using 0-based array is more convenient than using 1-based array (just only it looks not so good in the first stage of analysis) in using the formula, for example ... If you want to control your chess-man not to jump out of the board [0..7] when you increase or decrease it ... then it's quite clear to apply this fomula,  

(x + 1) % 8 or (x - 1) % 8

I know this is not the really reason, but it flavors to use the 0-based array.

Moreover, if you would like to use the array for example from 10 to 99 , then I think the good way is to shift your index from 0 to 89 ... For instance,

#define SHIFT(x) ((x) - 10)

int A[90] ; // A[0] ... A[89]

So in your programs, just use SHIFT(x) instead of x to index your array.
Numerical Recipies have a one based array implementation:

Essentially, since 'C' arrays are just pointers, it is possible to create your 1-dimensional array as:

    float *a0 = calloc(  size_of_array, sizeof( float ) );  // zero based;

    float *a1 = calloc(  size_of_array, sizeof( float ) );
             a1 = &( a1[-1] );   // one based;


You can now access a1[n], which will be the 'n'th element.

=====

Note that there is no additional overhead to using this type of indexing.

====
IMHO:  This is useful for speed, for but not easy to document.  If you can spare the horsepower, use a class.


B.