2011-11-12 8 views
23

su cui sto lavorando un esercizio di K & R (es. 5-9) e stavo cercando di convertire matrice 2D dielementi in eccesso di inizializzazione scalare per puntatore a matrice di 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 programma originale

nel usando puntatori a un array di 13 interi come

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} 
}; 

Ma stampe compilatore avvertimento: gli elementi in eccesso nel initializer scalare.

Googling non ha aiutato e persino K & R scrive quando si passa la matrice a una funzione,

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

è uguale

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

risposta

25

I due sono solo parzialmente equivalenti. La differenza è che:

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} 
}; 

dichiara un array bidimensionale, che comprende l'parte spazio per l'array e assicurando che daytab riferimenti quella memoria. Tuttavia:

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} 
}; 

... dichiara solo un puntatore. Quindi stai provando a inizializzare un puntatore con un inizializzatore di array, che non funziona come previsto. Non c'è array; non c'è memoria riservata per un array. Quello che succede invece è che il primo numero nel tuo inizializzatore è assegnato al puntatore daytab, e il compilatore genera un avvertimento per farti sapere che hai specificato molti valori aggiuntivi che sono appena scartati. Poiché il primo numero nel tuo inizializzatore è 0, stai semplicemente impostando daytab su NULL in modo piuttosto dettagliato.

Quindi, se si desidera eseguire questa sorta di inizializzazione, utilizzare la prima versione - decade allo stesso tipo di puntatore che si dichiara esplicitamente nella seconda versione, quindi è possibile utilizzarlo allo stesso modo. La seconda versione, con il puntatore dell'array, è necessaria quando si desidera allocare dinamicamente l'array o ottenere un riferimento a un altro array già esistente.

Così si può fare questo:

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

ptr = arr; 

... e poi usare ptr e arr intercambiabile. O questo:

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

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

... ottenere una allocato dinamicamente matrice a 2 dimensioni (non un array di puntatori ad array 1D, ma una matrice 2D reale). Ovviamente, non è inizializzato in quel caso.

L'"equivalenza" delle due varianti significa semplicemente che l'array 2D, quando decede da un puntatore al suo primo elemento, decade al tipo di puntatore dichiarato nella seconda variante. Una volta che la versione del puntatore è effettivamente puntata su un array, i due sono equivalenti. Ma la versione di array 2D imposta la memoria per l'array, dove la dichiarazione del puntatore non ... e al puntatore può essere assegnato un nuovo valore (puntato su un diverso array) in cui la variabile di array 2D non può.

In C99 si può fare questo, anche se (se non static almeno):

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

spazio Pila? Se è statico, entra nella sezione dei dati. –

+0

@BrianGordon corretto ... Ho dimenticato la "statica" durante la digitazione di quella parte (penso ... è stato tanto tempo fa). – Dmitri

+0

e quindi si può accedere al puntatore in questo modo '(* (daytab + leap)) [i]' (per quanto riguarda l'esercizio) – Vladimir

Problemi correlati