8

Possible Duplicate:
Defend zero-based arrays

I'm running code that loops through an array of HTML IDs.

With the HTML IDs named content1, content2, …, content12, my loop looks like:

for (var i = 1; i<13; i++) {
    var contentFind = $('#content'+i)[0];

I know that the usual way to run loops is to start at i = 0. Is there any benefit to this, or is it just the traditional, standard or normal way to write loops?

Ryan
  • 125
  • 1
  • 6
  • Heck, start at the top (12) and work your way down if you want... – AJC Sep 26 '11 at 14:02
  • Actually, this can be a very useful technique, if, for instance, you want to start at `array.length` and work downwards. It reduces the number of property accesses to your arrays, thus increasing the efficiency of the loop. – Ryan Kinal Sep 26 '11 at 14:05
  • Only if your compiler is dumb and doesn't optimize for you. (exception: C#, where the compiler will check the array length each time because it can change) – Malfist Sep 26 '11 at 14:11
  • @Malfist: True for any language, where the array length can change, including the language of this topic (JavaScript). That being said, with a bit of flow analysis, a proper JIT should be able to find out all *trivial* cases, where the array length won't change. – back2dos Sep 26 '11 at 14:17
  • Ask Dijkstra http://www.cs.utexas.edu/~EWD/transcriptions/EWD08xx/EWD831.html – Christian Kjær Sep 26 '11 at 15:44

3 Answers3

35

Start your for loops where ever you have to start them.

The reason a lot of for loops start at 0 is because they're looping over arrays, and in most languages (including JavaScript) arrays start at index 0.

Ryan Kinal
  • 1,481
  • 10
  • 14
5

In modern languages, you may think of it as tradition. There is a reason why it was done so originally though, and that reason was: to conserve memory.

(EDIT: Since 2 people have completely snapped already; I understand that arrays could have been implemented differently in C. The fact remains that they weren't. They really are just pointers in C, and C just so happens to be the ancestor of most modern languages which start at 0. - There may be other reasons to start at 0, I am merely providing the one related to how arrays work in the ancestor of C-style languages... the programming language C. Not Fortran, but C. Thank you for your understanding.)

The godfather of general-purpose programming languages, C (and by extension, C++), considers certain variables as memory addresses called pointers. These days, memory management is left up to the runtime environment, not the programmer which is why you've probably never heard of pointers. But when you use C, when you use variables, you're really dealing with the memory in a less abstract fashion.

This may be way too complicated if you're new to programming, but hopefully this will make some sense.

A pointer is a kind of variable that stores a memory address. In C, you can work with "normal" variables but they are limited in a number of ways... you always end up having to work with so-called pointers, which you may consider a different kind of variable, one that points to a location in memory, rather than the actual content of that location in memory. I will skip the discussion on why this is, just remember that pointers are variables containing memory addresses which then are used to point toward the data... as opposed to storing the data itself. ("Normal" variables are said to be located on the stack, but pointers are said to be located on the heap - nevermind this if it confuses you.)

In C, when you use an array, what you really have is a memory address (a pointer) indicating the start of the array. The pointer itself doesn't contain the content, it doesn't even contain the length of the array, merely the memory address of its starting point. But when you allocate that memory, you have to specify exactly how large the array is, so that the compiler will know how much memory to allocate.

Let's imagine an array in C called some_array.

some_array will determine the memory location of the array. The array itself is nothing but a sequence of reserved memory address space where the content of some_array is expected to reside. When we create that array, we give it a name (some_array), and we tell it how many items in the array we need. (In C/C++, arrays don't expand on demand, you have to declare their size beforehand or otherwise use more complicated classes like lists or vectors).

But now we want the second entry in our array. How do we figure out where it is? We only have the memory address, the pointer! That doesn't tell us where the second entry is, merely where the first entry starts!

But what we do know (in C), is the size of the variable type of our array... which also must be explicitly stated when you create the array. If we have an integer, for instance, let's say it's 16 bits in size.

We can then know the location of the second entry by knowing the location of the first entry (which is the start of the array), and then we can simply add the size of each entry (size of integer)!

In other words;

location_of_second_entry = location_of_first_entry + (size_of_integer).

What about the third entry? That will be:

location_of_third_entry = location_of_first_entry + (2 * size_of_integer).

As you might be able to tell, the physical memory location will always be as follows:

location_of_any_entry = location_of_first_entry + (iterator * size_of_integer)

So if you want the first item, the iterator will be 0. And that's why iterators originally started as 0, because the variables used to denote arrays were typically just memory addresses.

Now, this wouldn't have to work this way. You might start at 1 in C, but then you would be wasting the address space between the first entry and the second one because "location_of_first_entry" would never be used to store any data.

Memory management is handled completely differently in more recent runtimes and languages, so this is not really a technical requirement for more high-level programming languages (such as PHP, Python, Perl), but it's a tradition that has lived on because there was a time when programmers were expected to handle memory with some respect.

In more high-level languages, the question of whether to start from 0 or 1 is mostly a question of how much programmers feel like arguing about it. So, in the end of the day for 2011 and super-high-level programming languages, it's really just a tradition. - Apparently I'm a complete idiot that knows nothing about anything, spouting utter nonsense to the detriment of humanity and the world as we know it. Well, actually, I just neglected to take into account the modern debate and so I have earned the wrath of those who graciously know better. Turns out there's a perfectly rational debate around this that relates to modern languages, independent of the historical reasons behind C-style languages. So while the historical reason for C-style languages taking it from C is true, there is apparently a deeper discussion as well, as it turns out.

(EDIT: Since someone mentioned it, this was done differently, starting at 1, in other low-level programming languages like Fortran. The reason it was done this way in C is because of how arrays are implemented in C. They could have implemented them differently, in which case it could have started at 1 without wasting memory, but they didn't.)

Teekin
  • 599
  • 4
  • 7
  • 1
    (After cooling off a bit, I took back the -1.) The statement about wasting the address space between the first and second entry is utterly bogus. C started arrays at zero because it slightly simplified a quick-and-dirty compiler for a quick-and-dirty language. FORTRAN started arrays at 1, at least through FORTRAN 77, because mathematics starts counting at 1. Pascal and Ada both allow arrays to start at any reasonable integer value, positive OR negative. The compiler knows the starting index, and can offset the addressing appropriately. – John R. Strohm Sep 26 '11 at 15:30
  • Yes, a quick-and-dirty language where arrays are basically pointers. I see no contradiction. Given how arrays are done in C, it will too waste memory to start at 1. If they were implemented differently, then sure, you could avoid that. What am I missing? – Teekin Sep 26 '11 at 15:42
  • Sorry, but this is just utter bullshit. You can implement an array that starts at 1 without wasting memory by implementing array as a pointer to the address before the first element. Start an array at 1 was a tradition brought from ancient mathematics before `0` was invented; starting an array at 0 is logically consistent and logically simplest compared to the other alternatives. It is a logical choice to count from 0, it is tradition to count from 1. – Lie Ryan Sep 26 '11 at 18:52
  • 1
    Array in C starts at 0 because it leads to less bugs. See Dijkstra's article linked by @Christian Kjær's answer (Why numbering should start at zero) for proof and experimental evidence that this is so. – Lie Ryan Sep 26 '11 at 18:57
  • Well, Lie Ryan, this "utter bullshit" is what I have read and heard many times as an explanation of the phenomenon and it makes perfect sense when arrays are defined as simple pointers, as indeed they are in C. Also, for like, the third time or so, I understand that it *could* have been implemented differently. The C language however quite simply wasn't implemented differently and this tradition lives on from C. I'm sure there are also logical reasons for starting at 0. That doesn't turn any other reason to "utter bullshit". – Teekin Sep 26 '11 at 20:45
  • You say "`Normal variables are said to be located on the stack, but pointers are said to be located on the heap`", but this isn't necessarily true. The pointer itself is usually on the stack, and the memory it points to can be *anywhere*: stack, heap, or anywhere else. – Charles Salvia Sep 27 '11 at 07:20
0

It is a traditional method of doing it that is relative to the iteration across an array as you're describing. In a lot of cases, iteration of this nature of this nature is used on a zero-index array, so it makes sense to initialize your indexing variable to match the index of the array.

Other than that, you should always initialize your array looping variable to be what you need rather than what convention shows.

Joel Etherton
  • 11,674
  • 6
  • 45
  • 55