stefan
stefan

Reputation: 10345

Pointer arithmetic disguised &(array[0])

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 + 0or 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 gotos , mallocs and of course this pointer thing, feel free to look at it online.

Upvotes: 4

Views: 363

Answers (5)

Thomas Matthews
Thomas Matthews

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

Theodoros Chatzigiannakis
Theodoros Chatzigiannakis

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 nth element of the array", rather than "the nth 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

leemes
leemes

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

Pubby
Pubby

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

Ed Swangren
Ed Swangren

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

Related Questions