12

I know this has been hashed over a number of time, but I have come across a case today that shook my understanding of the pointer math/ array index.

As I have allways understood it, &mybuff[10] and (&mybuff+10) are equivilent ways of referancing the same memory.

However I spent the morning fighting a case where:

memcpy(&mybuff+10,&in,8); 

overflowed the buffer, when compiled with optimization on and worked just fine when compiled for debugging.

While athe same time,

memcpy(&mybuff[10],&in,8); 

worked just fine in both cases.

Many thanks for any ideas or pointers.

Paul Sasik
  • 79,492
  • 20
  • 149
  • 189
Bill N.
  • 835
  • 1
  • 7
  • 13
  • 11
    tee hee at the pun asking for "pointers" – Daniel Aug 18 '11 at 20:58
  • 9
    [Some pointers](http://xkcd.com/138/). – mopsled Aug 18 '11 at 21:06
  • 1
    `&mybuff[10]` evaluates to `&(*(mybuff+10))`, which is different from `&mybuff + 10`. Remember that postfix operators like `[]` have higher precedence than unary operators like `&`. – John Bode Aug 18 '11 at 21:06
  • possible duplicate of [C: How come an array's address is equal to its value?](http://stackoverflow.com/questions/2528318/c-how-come-an-arrays-address-is-equal-to-its-value) – Jerry Coffin Aug 18 '11 at 21:51

7 Answers7

8

I'll invent a declaration for mybuff for the sake of the example:

char mybuff[123];

Now, &mybuff+10 does pointer arithmic on &mybuff, which has the type "pointer to array of 123 chars". This is different from plain mybuff which (after pointer decay) has type "pointer to char". The bit value of these two expressions is the same, but because they are pointers to things of different sizes, they behave differently under pointer arithmetic.

&mybuff+10 means that you want to step past ten of the 123-char arrays in the type (which is meaningless given the declaration and may segfault), whereas mybuff+10 just says that you want to step past ten individual chars.

hmakholm left over Monica
  • 23,074
  • 3
  • 51
  • 73
7

see http://cplusplus.com/doc/tutorial/operators/ for priority order of operators
&mybuff+10 like (&mybuff)+10
&mybuff[10] like &(mybuff[10])

Edit
also some pointers http://cplusplus.com/doc/tutorial/pointers/

Taras Mazepa
  • 604
  • 8
  • 24
5

&mybuff[10] is equivalent to &mybuff[0] + 10 which is equivalent to mybuff + 10

Array indexing is defined in terms of pointer arithmetic. p[i] means *(p+i) (I'm ignoring the need for extra parentheses in case p or i is a more complex expression), where p is a pointer value and i is an integer value.

Trivia: Since addition, even pointer+integer addition, is commutative, p[i] can also be written as i[p]. Yes, 4["Hello"] == 'o'. For the sake of anyone who reads your code in the future, please do not make use of this knowledge.

An excellent reference on the relationship between arrays and pointer in C (and C++, where the rules are nearly identical) is section 6 of the comp.lang.c FAQ. (I could have linked directly to section 6, but I like to encourage people to browse it; the whole thing is worth reading.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
2

I think you've got some pointer problems.
If mybuff is a pointer then mybuff + 10 == &(mybuff[10]).
That's not the same as &mybuff + 10 like you've got there.

Taras Mazepa
  • 604
  • 8
  • 24
user12861
  • 2,358
  • 4
  • 23
  • 41
2

(&mybuff+10) and &mybuff[10] are not equivalent, but &mybuff[10] and mybuff + 10 are.

Janick Bernet
  • 20,544
  • 2
  • 29
  • 55
  • Not quite; `&mybuff[10]` parses as `&(mybuff[10])`, which is evaluated as `&(*(mybuff + 10))`. – John Bode Aug 18 '11 at 21:08
  • Which is equivalent to `mybuff + 10`. – Janick Bernet Aug 18 '11 at 21:10
  • just remove or edit first line of our answer, because it is not clear for beginners – Taras Mazepa Aug 18 '11 at 21:12
  • If we want to be completely language-lawyery about it, the correct thing to say would be that _whenever `&mybuff[10]` has a defined behavior_, that behavior is the same as `mybuff+10`. However, if mybuff is a 10-element array, then the implied deference in `&mybuff[10]` is past the end of the object and _arguably_ triggers undefined behavior (though I think I've seen others argue that it doesn't count as a dereference for that purpose when the `*foo` is immediately consumed by an address-of operator), whereas `mybuff+10` is defined. – hmakholm left over Monica Aug 18 '11 at 21:23
1

The correct syntax is mybuff+10 not &mybuff+10 which says move to position 10 in your array and copy 8 bytes (per your memcpy statement). It is still unknown whether you can actually hold an additional 8 bytes though.

  • @user12861: Go here - http://www.learncpp.com/cpp-tutorial/68-pointers-arrays-and-pointer-arithmetic/ –  Aug 18 '11 at 21:07
  • I'm saying this answer isn't clear. Personally, I know at least this much C++. – user12861 Aug 18 '11 at 21:08
  • @user12861: I'm sure the OP understands what the hell I am talking about. It is very clear. –  Aug 18 '11 at 21:15
1

The reason it worked in debug mode is because in debug mode, the memory is initialized for you and allocations are also larger than the actual size. http://msdn.microsoft.com/en-us/library/bebs9zyz(v=vs.80).aspx

EbbnFlow
  • 653
  • 1
  • 9
  • 17