He aquí el texto exacto de la norma C (n1256):
6.3.2.1 Lvalues, arrays y designadores de función
...
3 Excepto cuando es el operando de la
sizeof
operador o el unario
&
operador, o es una cadena literal utilizado para inicializar una matriz, una expresión que tiene el tipo '' gama de
tipo '' se convierte en una expresión con el tipo '' puntero a
tipo ’Que apunta al elemento inicial del objeto de matriz y no es un lvalue. Si el objeto de matriz tiene una clase de almacenamiento de registro, el comportamiento no está definido.
Lo importante a recordar aquí es que hay una diferencia entre un objeto (en términos de C, es decir, algo que ocupa la memoria) y el expresión utilizada para referirse a ese objeto.
Cuando se declara una matriz tal como
int a[10];
la objeto designado por la expresión a
es una matriz (es decir,, un bloque contiguo de memoria lo suficientemente grande como para contener 10 int
valores), y el tipo de la expresión a es "matriz de 10 elementos de int
" o int [10]
. Si la expresión a
aparece en un contexto que no sea el operando de los operadores sizeof
o &
, entonces su tipo se convierte implícitamente en int *
, y su valor es la dirección del primer elemento.
En el caso de que el operador sizeof
, si el operando es una expresión de tipo T [N]
, entonces el resultado es el número de bytes en el objeto de matriz, no en un puntero a ese objeto: N * sizeof T
.
En el caso de que el operador &
, el valor es la dirección de la matriz, que es la misma que la dirección del primer elemento de la matriz, pero el tipo de la expresión es diferente: dada la declaración T a[N];
, el tipo de la expresión &a
es T (*)[N]
, o el puntero a la matriz N-elemento de T. el valor es el mismo que a
o &a[0]
(la dirección de la matriz es la misma que la dirección del primer elemento de la array), pero la diferencia en tipos importa. Por ejemplo, teniendo en cuenta el código
int a[10];
int *p = a;
int (*ap)[10] = &a;
printf("p = %p, ap = %p\n", (void *) p, (void *) ap);
p++;
ap++;
printf("p = %p, ap = %p\n", (void *) p, (void *) ap);
verá la salida del orden de
p = 0xbff11e58, ap = 0xbff11e58
p = 0xbff11e5c, ap = 0xbff11e80
OIA, avanzando p
añade sizeof int
(4) al valor original, mientras que el avance ap
añade 10 * sizeof int
(40)
Más lenguaje estándar:
6.5.2.1 subíndices de matriz
Restricciones
1 Una de las expresiones tendrán el tipo '' puntero al objeto
tipo '', el otro expresión tendrá un tipo entero, y el resultado tiene el tipo ''
tipo ''.
Semántica
2 una expresión postfix seguido de una expresión en corchetes
[]
es una designación subindicada de un elemento de un objeto array. La definición del operador de subíndice
[]
es que
E1[E2]
es idéntico a
(*((E1)+(E2)))
. Debido a las reglas de conversión que se aplican a la
+
operador binario, si
E1
es un objeto array (equivalentemente, un puntero al elemento inicial de un objeto de matriz) y
E2
es un número entero,
E1[E2]
designa el elemento -ésimo
E2
de
E1
(conteo de cero).
Por lo tanto, cuando se subraya una expresión de matriz, lo que sucede debajo del capó es que se calcula el desplazamiento desde la dirección del primer elemento en la matriz y se desreferencia el resultado.La expresión
a[i] = 10;
es equivalente a
*((a)+(i)) = 10;
que es equivalente a
*((i)+(a)) = 10;
que es equivalente a
i[a] = 10;
Sí, subíndices de matriz en C es conmutativo; por el amor de Dios, nunca hagas esto en el código de producción.
Desde subíndices de matriz se define en términos de las operaciones de puntero, se puede aplicar el operador subíndice a las expresiones de tipo de puntero, así como el tipo de matriz:
int *p = malloc(sizeof *p * 10);
int i;
for (i = 0; i < 10; i++)
p[i] = some_initial_value();
Aquí hay una tabla práctica de recordar algunos de estos conceptos:
Declaration: T a[N];
Expression Type Converts to Value
---------- ---- ------------ -----
a T [N] T * Address of the first element in a;
identical to writing &a[0]
&a T (*)[N] Address of the array; value is the same
as above, but the type is different
sizeof a size_t Number of bytes contained in the array
object (N * sizeof T)
*a T Value at a[0]
a[i] T Value at a[i]
&a[i] T * Address of a[i]
Declaration: T a[N][M];
Expression Type Converts to Value
---------- ---- ------------ -----
a T [N][M] T (*)[M] Address of the first subarray (&a[0])
&a T (*)[N][M] Address of the array (same value as
above, but different type)
sizeof a size_t Number of bytes contained in the
array object (N * M * sizeof T)
*a T [M] T * Value of a[0], which is the address
of the first element of the first subarray
(same as &a[0][0])
a[i] T [M] T * Value of a[i], which is the address
of the first element of the i'th subarray
&a[i] T (*)[M] Address of the i-th subarray; same value as
above, but different type
sizeof a[i] size_t Number of bytes contained in the i'th subarray
object (M * sizeof T)
*a[i] T Value of the first element of the i'th
subarray (a[i][0])
a[i][j] T Value at a[i][j]
&a[i][j] T * Address of a[i][j]
Declaration: T a[N][M][O];
Expression Type Converts to
---------- ---- -----------
a T [N][M][O] T (*)[M][O]
&a T (*)[N][M][O]
*a T [M][O] T (*)[O]
a[i] T [M][O] T (*)[O]
&a[i] T (*)[M][O]
*a[i] T [O] T *
a[i][j] T [O] T *
&a[i][j] T (*)[O]
*a[i][j] T
a[i][j][k] T
A partir de aquí, el patrón para las matrices de mayor dimensión debe ser claro.
Por lo tanto, en resumen: las matrices no son punteros. En la mayoría de los contextos, las expresiones de matriz se convierten a tipos de puntero.
posible duplicado de una pregunta de C++ - faq del sitio: [¿El nombre de la matriz es un puntero en C?] (Http://stackoverflow.com/questions/1641957/is-array-name-a-pointer-in- c) –