0

In the question Find size of array without using sizeof in C the asker treats an int array like an array of int arrays by taking the address and then specifying an array index of 1:

int arr[100];
printf ("%d\n", (&arr)[1] - arr);

The value ends up being the address of the first element in the "next" array of 100 elements after arr. When I try this similar code it doesn't seem to do the same thing:

int *y = NULL;
printf("y = %d\n", y);
printf("(&y)[0] = %d\n", (&y)[0]);
printf("(&y)[1] = %d\n", (&y)[1]);

I end up getting:

y = 1552652636
(&y)[0] = 1552652636
(&y)[1] = 0

Why isn't (&y)[1] the address of the "next" pointer to an int after y?

Community
  • 1
  • 1
hcabrams
  • 131
  • 9

3 Answers3

8

Here:

printf("(&y)[1] = %d\n", (&y)[1]);

You say first: take address of y. Then afterwards you say: add 1 times so many bytes as the size of the thing which is pointed to - which is pointer to int, and hence probably 4 bytes are added - and dereference whatever is that on that address. But you don't know what is on that new memory address and you can't/shouldn't access that.

Giorgi Moniava
  • 27,046
  • 9
  • 53
  • 90
2

Arrays are not pointers, and pointers are not arrays.

The "array size" code calculates the distance between two arrays, which will be the size of an array.
Your code attempts to calculate the distance between two pointers, which should be the size of a pointer.

I believe the source of confusion is that (&y)[1] is the value of the "next" pointer to an int after y, not its address.

Its address is &y + 1.

In the same way, the address of y is &y, and (&y)[0] - or, equivalently *(&y) - is y's value.

(In the "array size" code, (&arr)[1] is also the "next" value, but since this value is an array, it gets implicitly converted to a pointer to the array's first element — &((&array)[1])[0].)

If you run this:

int *y = NULL;
printf("y = %p\n", y);
printf("&y = %p\n", &y + 0);
printf("&y + 1 = %p\n", &y + 1);

the output looks somewhat like this:

y = (nil)
&y = 0xbf86718c
&y + 1 = 0xbf867190

and 0xbf867190 - 0xbf86718c = 4, which makes sense with 32-bit pointers.

Accessing (&y)[1] (i.e. *(&y + 1)) is undefined and probably results in some random garbage.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
0

Thanks for the answers, I think the simplest way to answer the question is to understand what the value of each expression is. First we must know the type, then we can determine the value

I used the c compiler to generate a warning by assigning the values to the wrong type (a char) so I could see exactly what it thinks the types are.

Given the declaration int arr[100], the type of (&arr)[1] is int [100].

Given the declaration int *ptr, the type of (&ptr)[1] is int *.

The value of a int[100] is the constant memory address of where the array starts. I don't know all the history of why that is exactly.

The value of a int * on the other hand is whatever memory address that pointer happens to be holding at the time.

So they are very different things. To get the constant memory address of where a pointer starts you must dereference it. So &(&ptr)[1] is int ** which the constant memory address of where the int pointer starts.

hcabrams
  • 131
  • 9