Pointers and arrays are completely different things. Any similarity and confusion between the two is an artifact of the C language.
A pointer is a variable which holds the location of another variable. An array (in C) is an aggregate of values of identical type, consecutively allocated in memory.
Arrays are accessed via arithmetic upon a pointer to the base element, [0]
. If an expression which refers to an array is evaluated, the value which emerges is a pointer to element [0]
.
int array[10];
int *p = array; /* array expression yields pointer to array[0] */
int *q = &array[0]; /* q also points to same place as p */
The array notation in C is a sham which actually works with pointers. The syntax E1[E2]
means the same thing as *(E1 + E2)
(assuming that E1 and E2 are sufficiently parenthesized that we don't have to be distracted by associativity and precedence.) When we take the address of an element via &E1[E2]
, this is the same as &*(E1 + E2)
. The address-of and dereference "cancel out" leaving E1 + E2
. Therefore, these are also equivalent:
int *r = array + 3;
int *q = &array[3];
Because array[i]
and pointer[i]
are both valid syntax, people in the newbie stage (mistaking syntax to be semantics) conclude that arrays and pointers are somehow the same thing.
Spend some time programming in an assembly language. In assembly language, you might define some storage like this:
A: DFS 42 ;; define 42 words, labelled as A.
Then use it like this:
MOV R13, A ;; address of A storage is moved into R13
MOV R1, [R13 + 3] ;; load fourth word, A[3]
R13 points to the storage. That doesn't mean A is a pointer. A is the name of the storage. Of course to use the storage, we need its effective address and so a reference to A resolves to that. When the code is assembled and linked, that MOV
instruction will end up loading some numeric address into R13.
C is just a higher level assembly language. Arrays are like named storage which resolves to its effective address (being a pointer data type).
Arrays do not always resolve to their effective address. sizeof a
calculates the size of an array a
in bytes, whereas sizeof p
calculates the size of the pointer data type p
.
Another difference is that the name of an array cannot be made to refer to any place other than that array, whereas we can assign values to pointers:
array++; /* invalid */
array = &array[0]; /* invalid */
p = &array2[0]; /* valid */
p++; /* valid: point to the next element in array2 */