int g[] = {9,8};
Esto declara un objeto de tipo int [2], e inicializa sus elementos a {9 , 8}
int (*j) = g;
Esto declara un objeto de tipo int *, y lo inicializa con un puntero al primer elemento de g.
El hecho de que la segunda declaración inicialice j con algo que no sea g es bastante extraño. C y C++ solo tienen estas reglas extrañas sobre las matrices, y esta es una de ellas. Aquí la expresión g
se convierte implícitamente de un lvalue que hace referencia al objeto g en un valor r de tipo int*
que apunta al primer elemento de g.
Esta conversión se produce en varios lugares. De hecho, ocurre cuando haces g[0]
. El operador de índice de matriz en realidad no funciona en matrices, solo en punteros. Por lo tanto, la instrucción int x = j[0];
funciona porque g[0]
pasa a hacer la misma conversión implícita que se realizó cuando se inicializó j
.
Un puntero a una matriz se declara como esto
int (*k)[2];
y que está en lo cierto acerca de cómo esto se utilizaría
int x = (*k)[0];
(observar cómo "declaration follows use", es decir, la sintaxis para declarar una variable de un tipo imita la sintaxis para usando una variable de ese tipo.)
Sin embargo, uno no suele usar un puntero a una matriz. El propósito total de las reglas especiales en torno a las matrices es que puede usar un puntero a un elemento de la matriz como si fuera una matriz. Por lo tanto, a la C idiomática generalmente no le importa que las matrices y punteros no sean la misma cosa, y las reglas le impiden hacer mucho de lo que sea útil directamente con las matrices. (Por ejemplo no se puede copiar una matriz como: int g[2] = {1,2}; int h[2]; h = g;
)
Ejemplos:
void foo(int c[10]); // looks like we're taking an array by value.
// Wrong, the parameter type is 'adjusted' to be int*
int bar[3] = {1,2};
foo(bar); // compile error due to wrong types (int[3] vs. int[10])?
// No, compiles fine but you'll probably get undefined behavior at runtime
// if you want type checking, you can pass arrays by reference (or just use std::array):
void foo2(int (&c)[10]); // paramater type isn't 'adjusted'
foo2(bar); // compiler error, cannot convert int[3] to int (&)[10]
int baz()[10]; // returning an array by value?
// No, return types are prohibited from being an array.
int g[2] = {1,2};
int h[2] = g; // initializing the array? No, initializing an array requires {} syntax
h = g; // copying an array? No, assigning to arrays is prohibited
Debido arrays son tan incompatibles con los otros tipos en C y C++ que sólo debe evitar ellos. C++ tiene std::array
que es mucho más consistente y debe usarlo cuando necesite matrices de tamaño estático. Si necesita matrices de tamaño dinámico, su primera opción es std :: vector.
@mjfgates: las matrices no son punteros. Deja de decirle a la gente eso. –
@mjfgates De hecho, hay un objeto de matriz en C y C++. Simplemente sucede que hay reglas extrañas que, por ejemplo, causan conversiones implícitas de una matriz a un puntero al primer elemento de la matriz. – bames53