4

Could someone explain this little code snippet for me?

Given:

int a[3] = {2,3,4};

Why does the following evaluate to true?

static_cast<void *>(a) == static_cast<void *>(&a); // Why is this true?

Is this saying that the address of a is the same as a? If so, why is this true?

tdashroy
  • 1,405
  • 1
  • 19
  • 18
  • It probably looks weird if you are new to C/C++. It's actually a convention left-over from C : it only applies to literal arrays (and I think function names/pointers) – kfmfe04 Feb 20 '13 at 14:30

3 Answers3

4

It is because address of the variable a concides with the address of the first element of array a. You can also think of a is &a[0] which is clearer when we say "the address of the first element of the array").

Another example,

struct X
{
    int i;
};

X x;

Here also the address of variable x concides with the address of x.i (which is the first element of the aggregate), so this would print 1:

std::cout << (&x == &(x.i)) << std::endl; //1

So in your case, &a is like &x, and a (or &a[0]) is like &(x.i).

Note that in C++ a and x are both called aggregate (see my answer here: What is an aggregate?)

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Hmm, so I understand that `a == &a[0]` does exactly this. In this case I thought we were de-refrencing (is this correct term?) to the 0th position in the array `a`, and then taking the address of that position, which is what is pointed to by `a` in the first place. But in the case of the original post I thought we would be comparing `a`, which is a pointer that stores an address to the first element of the array, to the address of this pointer `a`. Does this mean on the stack there is no actual local variable `a` that points to an an array on the stack? – tdashroy Feb 20 '13 at 05:33
  • (continued) How is this array handled on the stack? Maybe this will help to make it more clear to me. – tdashroy Feb 20 '13 at 05:40
  • @tdashroy: There is an actual local variable `a`, which is just the beginning of the array. The stack-space occupied by `a` is equal to `sizeof(a)` bytes, which is same as `sizeof(ElementType) * ElementCount`. – Nawaz Feb 20 '13 at 05:40
  • ohhhh...okay. I thought there would be a pointer `a` to some place on the stack which would be the beginning of the array. So just to be clear (sorry, last question I promise!), this is how it works for dynamic arrays, which is why the same line doesn't evaluate to true for them? – tdashroy Feb 20 '13 at 05:48
  • @tdashroy: For dynamic array, say `int *b = new int[100]`, only the pointer is put on the stack (which takes usually `4` or `8` bytes, depending on the size of the pointer), and the elements reside somewhere else whose address is stored in the pointer `b`. In this case, `&b` and `b` are not same, though `b` and `&b[0]` are same! – Nawaz Feb 20 '13 at 05:57
1

In almost all contexts, the name of an array decays into a pointer to the first element of the array. So in static_cast<void*>(a), the a decays into &a[0]; it's type is "pointer to int". The expression evaluates to the address of the first element of the array. In static_cast<void*>(&a), however, &a is the address of the array itself; its type is "pointer to array of 3 int". That's why the casts are needed here: the two expressions without the casts would have different types, and could not be compared. Both can be converted to void* and compared. So what this code is illustrating is that the address of the first element of an array is the same as the address of the array, i.e., there's no padding at the front.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
0

The name of an array usually evaluates to the address of the first element of the array, so array and &array have exact the same value.

However, they are different types. For the following array:

int a[8];

a+1 is the address of the array a + sizeof(int) but &a+1 will be the address of the array a + 8 * sizeof(int).

StarPinkER
  • 14,081
  • 7
  • 55
  • 81