I read this in my book (and many sources on the internet):
The array variable points to the first element in the array.
The array variable is the whole array. It decays into a pointer to the first element of the array.
If you look at the types:
msg
is of type char [16]
&msg
is of type char (*)[16]
&msg[0]
is of type char *
So in a context where msg
can decay into an array, for example when passed as an argument, its value would be equal to &msg[0]
.
Let me draw this:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
|s|t|a|c|k| |o|v|e|r| |f|l|o|w|\0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
Imagine the starting point of this array, where 's'
is located is address 0x12345678
.
msg
itself, refers to the whole 16 bytes of memory. Like when you say int a;
, a
refers to 4 bytes of memory.msg[0]
is the first byte of that 16 bytes.&msg
is the address where array begins: 0x12345678
&msg[0]
is the address of first element of array: 0x12345678
This is why the values of &msg
and &msg[0]
are the same, but their types are different.
Now the thing is, msg
by itself is not a first class citizen. You cannot for example assign arrays. That is why, in most of the cases, the array will decay into its pointer.
If you know function pointers, this is very similar:
int array[10];
int function(int);
int *var = array
, array
decays to a pointer (&array
)void *var = function
, function
decays to a pointer (&function
)Note that, in case of function pointers, we like to keep the type, so we write:
int (*var)(int) = function;
Similarly, you can do with arrays:
int (*var)[10] = array;
When you use an array expression, the compiler converts it to a pointer to the first element. This is an explicit conversion specified by the 1999 C standard, in 6.3.2.1 3. It is a convenience for you, so that you do not have to write &array[0]
to get a pointer to the first element.
The conversion happens in all expressions except when an array expression is the operand of sizeof
or the unary &
or is a string literal used to initialize an array.
You can see that an array and its first element are different by printing sizeof array
and sizeof array[0]
.
The array variable signifies the entire memory block the array occupies, not only the array's first element. So array
is not the same as array[0]
(cf. sizeof array / sizeof array[0]
). But the array's first element is located at the same memory address as the array itself.
Saying the array points to the first element is also incorrect, in most circumstances, an array expression decays into a pointer to its first element, but they are different things (again cf. sizeof
for example).
char myChar = 'A'
char msg[] = 'ABCDEFGH'
When you type myChar you get value. But with msg you get pointer to first char(for values you have to use msg[x])
msg = &msg[0]
This can help you to understand, I think.
In most circumstances, an expression of array type ("N-element array of T
") will be replaced with / converted to / "decay" to an expression of pointer type ("pointer to T
"), and the value of the expression will be the address of the first element in the array.
So, assuming the declaration
int a[10];
the type of the expression a
is "10-element array of int
", or int [10]
. However, in most contexts, the type of the expression will be converted to "pointer to int
", or int *
, and the value of the expression will be equivalent to &a[0]
.
The exceptions to this rule are when the array expression is the operand of the sizeof
or unary &
operators, or is a string literal being used to initialize another array in a declaration.
So, based on our declaration above, all of the following are true:
Expression Type Decays to Value ---------- ---- --------- ----- a int [10] int * address of the first element of a &a int (*)[10] n/a address of the array, which is the same as the address of the first element &a[0] int * n/a address of the first element of a *a int n/a value of a[0] sizeof a size_t n/a number of bytes in the array (10 * sizeof (int)) sizeof &a size_t n/a number of bytes in a pointer to an array of int sizeof *a size_t n/a number of bytes in an int sizeof &a[0] size_t n/a number of bytes in a pointer to int
Note that the expressions a
, &a
, and &a[0]
all have the same value (address of the first element of a
), but the types are different. Types matter. Assume the following:
int a[10];
int *p = a;
int (*pa)[10] = &a;
Both p
and pa
point to the first element of a
, which we'll assume is at address 0x8000
. After executing the lines
p++;
pa++;
however, p
points to the next integer (0x8004
, assuming 4-byte int
s), while pa
points to the next 10-element array of integers; that is, the first integer after the last element of a
(0x8028
).
Look at it this way:
&msg = 0x0012
&msg[0] = 0x0012
&msg[1] = 0x0013
In this case &msg[1]
is pointing to msg+1
. When you reference &msg
or &msg[0]
you are referring to the same address of memory because this is where the pointer starts. Incrementing the array variable will increment the pointer by +1 since a char variable is only 1 byte in size.
If you do the same trick with say an integer you will increment the pointer by +4 bytes since an integer is 4 bytes in size.