Hacker News new | ask | show | jobs
by halayli 3464 days ago
But arr != &arr even though they have the same value. #8 applies to arr (P), but in the post OP is using &arr which is a ptr to array[x] and doesn't apply to it.
3 comments

That's why I quoted paragraph 7: arr is not an element of an array, so &arr (being a pointer to an object which is not an element of an array) behaves like a pointer to the first element of an array of length one with the type of the arr as its element type.

So &arr behaves like it's a pointer to the start of int[5][1].

Yes &arr does behave like arr when it comes to ptr arithmetic but the compiler does not guarantee that &arr + 1 does not overflow. It only guarantees arr + 1. if you have a ptr from heap, ptr + 1 if not alloced previously is UB.

> If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow;

this point doesn't apply to &arr + 1.

How so? If the array has five elements, you can pass &arr to a function that expects an int[5][], and that function certainly can build a pointer that points one past the last element.

Likewise, the compiler ensures that you can build &arr[5] and that is the same address as &arr+1. &arr+1 cannot overflow.

The compiler guarantees that arr + 1 doesn't overflow by making sure arr's address is small enough to not overflow when accessing one element past the array size. &arr + 1 is not one past the array you asked the compiler to allocate.

if you're on a 16bit system and you define char x[36], the compiler guarantees that x's address is not more than 65500. if you do &x + 1 then you'll overflow, x + 1 won't.

You can pass whatever you want to the functions and apply the operands you want and the compiler will happily comply with you. But when you pass it 65500 and add 72 to it, it's going to overflow.

Wait, wait.

  char *p = x;
  p += 36; // overflow?
As arr == &arr, so are pointers P and Q that point just after last array item (1+&x[35]) and just after entire array (1+&x). As 6.5.6.8 above said, P is okay, and so must be Q. They said about last element, not second. Can you please explain why is x+1 even an argument?

>if you're on a 16bit system and you define char x[36], the compiler guarantees that x's address is not more than 65500 65499?

No, he is correct. The C and C++ standards do allow pointers past the last element of an array to be produced via a pointer to an element of said array. They also have a provision where a pointer to a nonarray value is treated as if it were a 1-element array (so you can do "int x; int* p = *x + 1"). But in this case, the value is obviously an array object, and it's not an element to another array; hence, it is not legal to do &arr + 1 ("... otherwise, the behavior is undefined").

This is 6.3.6 "Additive operators" in ISO C90 standard, for anyone curious.

Then you have a broken compiler.
Can't we declare pointer of type &arr, assign it there and be sure that it points to equivalent of array[1] of &arr? If yes, then is it logically possible to have UB on that?
You can define a pointer of type `int (*)[5]` and assign `(&arr)[1]` to it. That's fine, it's a pointer to the 5-element array just after the one we're sure is valid.

Dereferencing the pointer is UB, but you can create the pointer, assign it to a variable, etc.

I know it's not what you were trying to communicate, but actually "arr != &arr" is false.