Reputation: 10345
Today I browsed some source code (it was an example file explaining the use of a software framework) and discovered a lot of code like this:
int* array = new int[10]; // or malloc, who cares. Please, no language wars. This is applicable to both languages
for ( int* ptr = &(array[0]); ptr <= &(array[9]); ptr++ )
{
...
}
So basically, they've done "take the address of the object that lies at address array + x
".
Normally I would say, that this is plain stupidity, as writing array + 0
or array + 9
directly does the same. I even would always rewrite such code to a size_t for loop, but that's a matter of style.
But the overuse of this got me thinking: Am I missing something blatantly obvious or something subtely hidden in the dark corners of the language?
For anyone wanting to take a look at the original source code, with all it's nasty goto
s , malloc
s and of course this pointer thing, feel free to look at it online.
Upvotes: 4
Views: 363
Reputation: 57708
According to classical mathematics:
Array[n]
refers to the nth element in the array.
To "take the address of" the nth element, the &
or address of
operator is applied:
&Array[n]
To clear out any assumed ambiguities, parenthesis are added:
&(Array[n])
To a reader, reading from left to right, this expression has the meaning:
Return the address of the element at position 'n'
The insurance may have developed as a protection against old faulty compilers.
Some people consider it more readable than:
Array + n
Sorry, but I am old school and prefer using the '&' version, paren or without. I'll waste my time making code easier to read than worrying about which version takes longer to compile or which version is more efficient.
A clear commented section of code has a higher Return On Investment than a section of code that is micro-optimized for efficiency or uses sections of the language that are unfamilar to non language lawyers.
Upvotes: 1
Reputation: 29213
You're not missing anything, they do mean the same thing.
However, to try to shed some more light on this, I should say that I also write expressions like that from time to time, for added clarity.
I personally tend to think in terms of object-oriented programming, meaning that I prefer to refer to "the address of the n
th element of the array", rather than "the n
th offset from the beginning address of the array". Even though those two things are equivalent in C, when I'm writing the code, I have the former in mind - so I express that.
Perhaps that's the reasoning of the person who wrote this as well.
Upvotes: 2
Reputation: 45675
I think the reason why they wrote it this way was that
&(array[0])
and
&(array[9])
just look similar. Another way would be to write it
array + 0
and
array + 9
respectively. As you already mentioned, they essentially do the same (at least most compilers treat it as the same, I hope).
You could interpret the two different type of expressions differently: The first one can be read as "the address of element 0 / 9". The second one can be read as "array pointer with an element offset of 0 / 9". The first one sounds more high-level, the second more low-level. However, most people tend to use the second form, though.
Now since array + 0
of course is the same as array
, you could just write array
. I think the point here is that the begin and end of the loop look "analogous" to each other. A question of personal taste.
Upvotes: 1
Reputation: 53047
Edit: this is partially incorrect. Read the comments.
The problem with &(array[0])
is that it expands to &(*(array + 0))
which involves an dereference. Now, every compiler will obviously optimize this into the same thing as array + 0
, but as far as the language is concerned the dereference can cause UB in places where array + 0
would not.
Upvotes: 1
Reputation: 124672
Yeah, there's no good reason for the first one. This is exactly the same thing:
int *ptr = array;
I agree on the second also, may as well just write:
ptr < (array + 10)
Of course you could also just make it a for
loop from 0-9 and set the temp pointer to point to the beginning of the array.
for(int i = 0, *ptr = array; i < 10; ++i, ++ptr)
/* ... */
That of course assumes that ptr
is not being modified within the body of the loop.
Upvotes: 5