2011-11-12 9 views
23

que estoy trabajando en un ejercicio de K & R (p. 5-9) y yo estaba tratando de convertir la matriz 2D deexceso de elementos de inicializador escalar de puntero a matriz de INT

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} 
}; 
del programa original

en el uso de punteros a un array de 13 enteros 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 las impresiones del compilador advertencia: exceso de elementos en inicializador escalar.

Googling no ayuda e incluso K & R escribe al pasar la matriz a una función,

myFunction(int daytab[2][13]) {...} 

es la misma que

myFunction(int (*daytab)[13]) {...} 

Respuesta

25

Los dos son sólo en parte equivalente. El ser que diferencia:

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 de dos dimensiones, que incluye dejar de lado el espacio para la matriz y asegurar que daytab referencias que 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 ocurre en su lugar es que el primer número en su inicializador se asigna al puntero daytab, y el compilador genera una advertencia que le permite saber que ha especificado muchos valores adicionales que simplemente se descartan. Dado que el primer número en su inicializador es 0, simplemente 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.

Así que usted puede hacer esto:

static char arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; 
static char (*ptr)[3] = NULL; 

ptr = arr; 

... y luego usar ptr y arr indistintamente. O esto:

static char (*ptr)[3] = NULL; 

ptr = malloc(2 * sizeof(*ptr)); 

... para obtener una matriz de 2 dimensiones asignada dinámicamente (no una matriz de punteros a las matrices de 1D, 2D, pero una matriz real). Por supuesto, no se inicializa en ese caso.

La "equivalencia" de las dos variaciones solo significa que la matriz 2D, cuando se desintegra a 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.

En C99 que puede hacer esto, sin embargo (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} 
}; 
+0

espacio de pila? Si es estático, entra en la sección de datos. –

+0

@BrianGordon Corregido ... Me olvidé de la "estática" mientras escribía esa parte (creo ... fue hace mucho tiempo). – Dmitri

+0

y luego se puede acceder al puntero como este '(* (daytab + leap)) [i]' (con respecto al ejercicio) – Vladimir

Cuestiones relacionadas