Difference between dereferencing pointer and accessing array elements
arrays, c, dereference, pointers
Solution
Thanks to the link provided by @tesseract in the comments: Expert C Programming: Deep C Secrets (page 96), I came up with a simple answer (a simple dumb down version of the explanation in the book; for a full academic answer read the book):
- when declared `int a[2]`:
- the compiler has for `a` an address where this variable is stored. This address is also the address of the array since the type of the variable is array.
- Accessing `a[1]` means:
- retrieving that address,
- adding the offset and
- accessing the memory at this computed new address.
- when declared `int *b`:
- the compiler also has an address for `b` but this is the address of the pointer variable, not the array.
- So accessing `b[1]` means:
- retrieving that address,
- accessing that location to get the value of `b`, i.e. the address of the array
- adding an offset to this address and then
- accessing the final memory location.
Problem
I remember an example where the difference between pointers and arrays was demonstrated. An array decays to a pointer to the first element in an array when passed as a function parameter, but they are not equivalent, as demonstrated next: ``` //file file1.c int a[2] = {800, 801}; int b[2] = {100, 101}; ``` ``` //file file2.c extern int a[2]; // here b is declared as pointer, // although the external unit defines it as an array extern int *b; int main() { int x1, x2; x1 = a[1]; // ok x2 = b[1]; // crash at runtime return 0; } ``` The linker does not type-check for external variables so no errors are generated at compile time. The problem is that `b` is in fact an array, but the compilation unit `file2` is unaware of that and treats `b` as a pointer, resulting in a crash when trying to dereference it. I remember when this was explained it made perfect sense, but now I can't remember the explanation nor I can come up to it on my own. So I guess the question is how is an array treated differently than a pointer when accessing elements? (because I thought that `p[1]` is converted to (the assembly equivalent of) `*(p + 1)` regardless if `p` is an array or a pointer — I am obviously wrong). The assembly generated by the two dereferences (VS 2013): note: `1158000h` and `1158008h` are the memory addresses of `a` and `b` respectively ``` 12: x1 = a[1]; 0115139E mov eax,4 011513A3 shl eax,0 011513A6 mov ecx,dword ptr [eax+1158000h] 011513AC mov dword ptr [x1],ecx 13: x2 = b[1]; 011513AF mov eax,4 011513B4 shl eax,0 011513B7 mov ecx,dword ptr ds:[1158008h] 011513BD mov edx,dword ptr [ecx+eax] 011513C0 mov dword ptr [x2],edx ```