Is an array a pointer?
“Array is a pointer” (also “an array’s name is a pointer to the array’s first element”) – I think most of us have heard that nonsense. So many people believe it’s true. And some of them think that they’re absolutely right, don’t even taking into account they may be wrong. I’m getting tired of this, so… I think it’s great time to write a post about this ;>
Let’s see what the standard says (4.2.1): “An lvalue or rvalue of type ‘array of N T’ or ‘array of unknown bound of T’ can be converted to an value of type ‘pointer to T.’ The result is a pointer to the first element of the array”. It’s pretty clear it means that these types are convertible (and, since they’re convertible, they can’t be the same type). Someone who doesn’t know that may think they’re in fact the same, since it’s perfectly fine to do something like:
int foo[11]; int* bar = foo; *(foo + 8) = 42; void sth(int*); sth(foo);
Sure, it compiles and runs just fine. But this doesn’t mean that arrays are pointers. Consider this:
void function(float num); int x = /* ... */; function(x);
It compiles and runs fine, too. But it’s because of implicit conversion, not because the types are the same (I hope nobody thinks int and float are the same ;>).
If arrays and pointer actually were the same, then the following code wouldn’t compile:
template <typename T> struct sth; template <> struct sth<int []> {}; // okay, int [] and int [6] are distinct types template <> struct sth<int [6]> {}; // okay, int*, int [] and int [6] are distinct types template <> struct sth<int*> {}; // sizeof(pointer to int) is not equal to sizeof(array of six ints) // (in fact it could be true for a very obscure machine, though) typedef char x[sizeof(int*) != sizeof(int[6]) ? 1 : -1];
But what about “arrays” in function arguments list? Let’s suppose we have something like
void f(int arr[]) { }
In this function, arr is a pointer. sizeof(arr) will yield size of a pointer to int. It’s legal to do ++arr. It’s because an array passed to function by value decays to a pointer (this doesn’t mean that arrays are pointers!), arrays simply can’t be passed by value. Even if we’ll tell the compiler the size of the array:
void f(int arr[123]) { }
it’s still a pointer. And because it’s a pointer, it’s not possible to overload a function based on the size of the “array” passed “by value”. “Arrays” in argument lists are pointers. So overloading for int [123] and int [456] is ill-formed – they’re both int*.
If we really want to pass an array and not a pointer to the function, then we can pass a reference to an array (possibly making the hard-coded 123 a template parameter, so that the function can take arrays with different sizes):
// void f(const int (&arr)[123]) if array of consts void f(int (&arr)[123]) { }
It’s impossible to pass a pointer to this function, the code won’t compile. This function takes a reference to an array, so pointers won’t do:
int array[123]; int* pointer; f(array); // okay // f(pointer); // error
To sum up: pointers and arrays are two different things. They often behave similarly, they’re related, but they’re nonetheless different.

Cześć!
Dzięki za post ;>
Przyznaje, że zawszę traktowałem nazwę tablicy jako const pointer. I w sumie na pewnym poziomie abstrakcji nawet miałem rację ;>
Natomiast po tym poście przyznaje, że patrząc na poziomie kompilatora, faktycznie nazwa tablicy jest tablicą, a nie pointerem, i jest dopiero rzutowana na pointer ;> Chociaż upierał się będę, że w użyciu to za dużo nie zmienia.
Anyway, dorzucę w takim razie jeszcze jeden przykład do zacytowanych przez Ciebie – dla odmiany będzie to C, a konkretniej GCC i jego extenstion typeof() oraz opcja -fdump-tree-all:
Jeżeli typeof(a) było by const pointerem, to b powinno być const pointerem. Natomiast jeżeli typeof(a) jest tablicą 12 intów, to b będzie tablicą 12 intów. Zmienna c natomiast powinna być pointerem.
Na pytanie “jak jest w rzeczywistości” odpowie -fdump-tree-all (od 4.4.1 dostępne bodajże), czyli zrzut półproduktów kompilatora. A konkretniej .original:
Co w zasadzie sprawę przesądza ;>
Pozdrawiam!
Gynvael Coldwind powiedział Styczeń 17, 2010 @ 12:36