It's said that arrays "decay" into pointers. A C++ array declared as int numbers [5]
cannot be re-pointed, i.e. you can't say numbers = 0x5a5aff23
. More importantly the term decay signifies loss of type and dimension; numbers
decay into int*
by losing the dimension information (count 5) and the type is not int [5]
any more. Look here for cases where the decay doesn't happen.
If you're passing an array by value, what you're really doing is copying a pointer - a pointer to the array's first element is copied to the parameter (whose type should also be a pointer the array element's type). This works due to array's decaying nature; once decayed, sizeof
no longer gives the complete array's size, because it essentially becomes a pointer. This is why it's preferred (among other reasons) to pass by reference or pointer.
Three ways to pass in an array1:
void by_value(const T* array) // const T array[] means the same
void by_pointer(const T (*array)[U])
void by_reference(const T (&array)[U])
The last two will give proper sizeof
info, while the first one won't since the array argument has decayed to be assigned to the parameter.
1 The constant U should be known at compile-time.
You got it slightly wrong: moreThings
also decays to a pointer to the first element, but since it is an array of an array of chars, the first element is an "array of 8 chars". So the decayed pointer is of this type:
char (*p)[8] = moreThings;
The value of the pointer is of course the same as the value of &moreThings[0][0]
, i.e. of the first element of the first element, and also the same of &a
, but the type is a different one in each case.
Here's an example if char a[N][3]
:
+===========================+===========================+====
|+--------+--------+-------+|+--------+--------+-------+|
|| a[0,0] | a[0,1] | a[0,2]||| a[1,0] | a[1,1] | a[1,2]|| ...
|+--------+--------+-------+++--------+--------+-------++ ...
| a[0] | a[1] |
+===========================+===========================+====
a
^^^
||+-- &a[0,0]
|+-----&a[0]
+-------&a
&a
: address of the entire array of arrays of chars, which is a char[N][3]
&a[0]
, same as a
: address of the first element, which is itself a char[3]
&a[0][0]
: address of the first element of the first element, which is a char
This demonstrates that different objects may have the same address, but if two objects have the same address and the same type, then they are the same object.
Best Answer
C 2011 6.3.2.1 3:
In other words, arrays usually decay to pointers. The standard lists the cases when they do not.
One might think that arrays act as arrays when you use them with subscripts, such as
a[3]
. However, what happens here is actually:a
is converted to a pointer.a[3]
is evaluated as*((a)+(3))
. That is,a
is converted to a pointer, 3 is added to the pointer, and the ***** operator is applied.)Note: The C 2011 text includes “the _Alignof operator.” This was corrected in the C 2018 version of the standard, and I have elided it from the quote above. The operand of
_Alignof
is always a type; you cannot actually apply it to an object. So it was a mistake for the C 2011 standard to include it in 6.3.2.1 3.