matriz - punteros c++
Exceso de elementos de inicializador escalar para puntero a matriz de enteros (2)
@Dmitri lo explicó bien, pero quería agregar que
static char (*daytab)[13] { ... };
es un char pointer
a una matriz de 13 chars
. Como explicó K & R, sin los paréntesis, los corchetes []
tienen mayor precedencia, por lo que
static char *daytab[2] { ... };
produciría el efecto deseado de tener una matriz de 2 punteros de char. Ahora solo tenemos que inicializar los dos punteros para hacer referencia a una matriz char []
apropiada.
Opción 1:
static char *daytab[2] {
(char []) {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
(char []) {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
Opcion 2:
static char nonleap[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static char leap[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static char *daytab[2] = {nonleap, leap}
Estoy trabajando en un ejercicio en K & R (por ejemplo, 5-9) y estaba tratando de convertir el conjunto 2D del programa original de
static char daytab[2][13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
en el uso de punteros a una matriz de 13 ints como
static char (*daytab)[13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
Pero el compilador imprime advertencias: elementos en exceso en el inicializador escalar .
Google no ayudó e incluso K & R escribe al pasar la matriz a una función,
myFunction(int daytab[2][13]) {...}
es lo mismo que
myFunction(int (*daytab)[13]) {...}
Los dos son solo parcialmente equivalentes. La diferencia es que:
static char daytab[2][13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
declara una matriz bidimensional, que incluye reservar espacio para la matriz y garantizar que daytab
referencia a esa memoria. Sin embargo:
static char (*daytab)[13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
... solo declara un puntero. Por lo tanto, intenta inicializar un puntero con un inicializador de matriz, que no funciona como se esperaba. No hay matriz; no hay memoria reservada para una matriz. Lo que sucede, en cambio, es que el primer número en su inicializador se asigna a la daytab
del día del puntero, y el compilador genera una advertencia que le permite saber que ha especificado una gran cantidad de valores adicionales que simplemente se descartan. Dado que el primer número en su inicializador es 0
, solo está configurando daytab
en NULL
de una manera bastante detallada.
Por lo tanto, si desea realizar este tipo de inicialización, use la primera versión: decae al mismo tipo de puntero que declara explícitamente en la segunda versión, para que pueda usarlo de la misma manera. La segunda versión, con el puntero de matriz, es necesaria cuando desea asignar dinámicamente la matriz u obtener una referencia a otra matriz que ya existe.
Entonces puedes hacer esto:
static char arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
static char (*ptr)[3] = NULL;
ptr = arr;
... y luego usa ptr
y arr
indistintamente. O esto:
static char (*ptr)[3] = NULL;
ptr = malloc(2 * sizeof(*ptr));
... para obtener una matriz bidimensional dinámicamente asignada (no una matriz de punteros a matrices 1D, sino una matriz bidimensional real). Por supuesto, no se inicializa en ese caso.
La "equivalencia" de las dos variaciones solo significa que la matriz 2D, cuando se descompone en un puntero a su primer elemento, se desintegra al tipo de puntero declarado en la segunda variación. Una vez que la versión del puntero apunta a una matriz, las dos son equivalentes. Pero la versión de matriz 2D configura la memoria para la matriz, donde la declaración del puntero no ... y al puntero se le puede asignar un nuevo valor (apuntado a una matriz diferente) donde la variable de matriz 2D no puede.
Sin embargo, en C99 puedes hacer esto (si no static
al menos):
char (*daytab)[13] = (char [][13]){
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};