2

So for a while I was confused about array names and pointers.

We declare int a[10]; And somewhere down the road also have a and &a.

So I get how the syntax works. a is the array name. When it is not used as an operand for sizeof &, etc., it will be converted or "decayed" so it returns a pointer to integer holding the address of the first element of the array.

If the array name is used as an operand for sizeof or &, its type is int (*)[10]. So I guess the type is different because that "decay" does not happen.

But I still do not understand how &a works. My understanding is that it is giving me the address of whatever it was before the "decay" happened.. So before the "decay" to pointer happened, then what is it and how does the compiler work with the "original" to evaluate &a?

In comparison, if we declare int *p; and later have &p and p somewhere in the code...

In this case the pointer to integer p is given a separate pointer cell with its address and the value at that address will be whatever address we assign to it (or the garbage value at that address pre-assignment).

a does not get assigned a separate pointer cell in memory when it is declared int a[10]. I heard it is identified with an offset on the register %ebp. Then what is happening with the compiler when it evaluates &a? The "decay" to a pointer to integer is not happening, there was no separate "pointer" in the first place. Then what does the compiler identify a as and what does it do when it sees that unary & operator is using the array name as an operand?

7
  • That first code block only compiles in C because C treats all pointer types as compatible and the address of an array is the same as the address of the first element. In C++ it is a pointer type mismatch. Commented Apr 6, 2019 at 3:00
  • i will remove the c++ tag Commented Apr 6, 2019 at 3:01
  • @CruzJean a == &a is also a pointer type mismatch in C. Commented Apr 6, 2019 at 3:07
  • @chux Well ya, but as far as I'm aware C just emits a warning at best. Though I might just be used to old versions of C compilers. Commented Apr 6, 2019 at 3:10
  • 1
    Here's another example to consider: If you have int b[20][10], and for instance you pass b as a function argument, it decays to type int (*)[10]. This makes sense, since b[0] has type int [10], so &b[0] has type int (*)[10]. And of course, &b has type int (*)[20][10]. Commented Apr 6, 2019 at 3:22

3 Answers 3

3

Given:

int a[10]; 

the object a is of type int[10]. The expression a, in most but not all contexts, "decays" to a pointer expression; the expression yields a value of type int*, equivalent to &a[0].

But I still do not understand how &a works. My understanding is that it is giving me the address of whatever it was before the "decay" happened.. So before the "decay" to pointer happened, then what is it and how does the compiler work with the "original" to evaluate &a?

That's not quite correct. In &a, the decay doesn't happen at all. a is of type "array of 10 int" (int[10]), so &a is of type "pointer to array of 10 int" (int(*)[10]).

There's nothing special about this. For any name foo of type some_type, the expression &foo is of type "pointer to some_type". (What's confusing about it is that this is one of the rare cases where an array name doesn't behave strangely.)

It's best to think of the words "array" and "pointer" as adjectives rather than nouns. Thus we can have an array object, an array expression, an array type, and so forth -- but just "an array" is ambiguous.

This:

int a[10]; 

defines an array object named a (and allocates 4 * sizeof (int) bytes to hold it). No pointer object is created. You can create a pointer value by taking the address of the object, or of any element of it. This is no different than objects of any other type. Defining an object of type some_type doesn't create an object of type some_type*, but you can create a value of type some_type* by computing the address of the object.

Sign up to request clarification or add additional context in comments.

Comments

1

Then what does the compiler identify a as and what does it do when it sees that unary & operator is using the array name as an operand?

The compiler identifies a as a 10-element integer array, and when it sees the & operator, it returns the address of that array.

Just like it would see int i = 3; as an integer, and &i as the address of that integer.

2 Comments

i was over-thinking this problem a little bit.. and was actually getting to the same int x = 5; example to think about int a[10];
More than a little bit, it seems. :) Sometimes it helps to back away from the trees and try and see the forest.
0

Concerning taking the address of an array: an array is an object in and of itself, so it has both a size and an address (though taking its address is seldom useful).

The conversion of an array to a pointer to its first element is a form of type coercion. It only happens if the alternative would be a compile error.

For instance, you can't compare an array to a pointer, so the array (implicitly) is coerced (cast) to an int* (to its first element) and then the pointer types are compared. In C you can compare any pointer types. C just doesn't care (though it will likely emit a warning).

This is actually comparing int* to int(*)[10] as far as types are concerned, as you said. These will necessary have the same address (regardless of typing) because arrays hold their data directly. So the address of an array will always be the address of its first element.

However, it's not an error to get the size of an array, so sizeof(a) gets the size of the entire array, as no coercion is needed to make this legal. So this is the same as sizeof(int[10]).

Your other case sizeof(&a) is really sizeof(int(*)[10]) as you said.

12 Comments

sorry I guess my code blocks were misleading. I was not really asking about a == &a would compile? But what the compiler was doing when it encounters &a
sizeof(++a) (which is what I assume you mean), is an error, since a is not an l-value
@MarkBenningfield No, I meant sizeof(+a) it forces an array to pointer conversion. It's classically called the decay operator in this context.
Well, +a would result in an illegal operand error in C.
@namesake22 I think I've edited the answer to cover that better now - an array is an object, so it has both a size and an address.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.