2015-06-01 3 views
5

Quindi, stavo giocando con i puntatori C e l'aritmetica dei puntatori poiché non sono del tutto a loro agio con loro. Mi sono inventato questo codice.Riguardanti i puntatori a doppio e triplo/array a doppia dimensione

char* a[5] = { "Hi", "My", "Name", "Is" , "Dennis"}; 
char** aPtr = a; // This is acceptable because 'a' is double pointer 
char*** aPtr2 = &aPtr; // This is also acceptable because they are triple pointers 
//char ***aPtr2 = &a // This is not acceptable according to gcc 4.8.3, why ? 

//This is the rest of the code, the side notes are only for checking 
printf("%s\n",a[0]); //Prints Hi 
printf("%s\n",a[1]); //Prints My 
printf("%s\n",a[2]); //Prints Name 
printf("%s\n",a[3]); //Prints Is 
printf("%s\n",a[4]); //Prints Dennis 

printf("%s\n",*(a+0)); //Prints Hi 
printf("%s\n",*(a+1)); //Prints My 
printf("%s\n",*(a+2)); //Prints Name 
printf("%s\n",*(a+3)); //Prints Is 
printf("%s\n",*(a+4)); //Prints Dennis 

printf("%s\n",*(*(aPtr2) +0)); //Prints Hi 
printf("%s\n",*(*(aPtr2) +1)); //Prints My // ap = a, *ap = *a, *(ap)+1 = *a+1 ? 
printf("%s\n",*(*(aPtr2) +2)); //Prints Name 
printf("%s\n",*(*(aPtr2) +3)); //Prints Is 
printf("%s\n",*(*(aPtr2) +4)); //Prints Dennis 

char*** aPtr2 = &a non è accettabile secondo gcc 4.8.3, perché?

dispiace dimenticato di aggiungere avviso del compilatore:

avvertimento: l'inizializzazione dal tipo di puntatore incompatibili [abilitato per impostazione predefinita]

E 'forse poco chiaro quello che sto cercando di dire, così ho dovuto aggiungi questo link:

Notare le righe commentate.

+0

Per "non accettabile", cosa intendi? Si prega di includere l'avviso o il messaggio di errore. –

+3

Sei sicuro che si rompa? http://ideone.com/KM516t (Si noti che manca un punto e virgola e si sta riutilizzando il nome 'aPtr2') – mtijanic

+0

Il link' ideone' che ho postato lo ha compilato bene per gcc-4.9.2. Quali flag del compilatore stai usando? – mtijanic

risposta

1

Questo deriva dal modo in cui tratta gli array C e indirizzi:

int a[5]; 

a è del tipo int * const, vero, significa che è possibile utilizzarlo in cui è previsto un puntatore. Tuttavia, nello stack lo spazio per il puntatore non è allocato, solo lo spazio per i cinque interi. Significato a corrisponde a &a[0]. Tutto ciò è previsto, ma ecco la parte strana:

a è lo stesso di &a. Questo perché il puntatore non è memorizzato da nessuna parte, non è possibile ottenere il suo indirizzo. Ma invece di fallire la compilazione, lo standard C dice semplicemente che sono uguali, quindi funzionerà un po 'di aritmetica.

Tuttavia, dal momento che si sta facendo char ***aPtr2 = &a;, si sta effettivamente facendo char ***aPtr2 = a;, motivo per cui si ottiene un segfault. È solo un doppio puntatore, non un triplo.

È possibile controllare tutti i valori nel debugger per vedere più chiaramente, o eseguire un programma come ad esempio:

#include <stdio.h> 

int main(void) 
{ 
    char *a[5] = { "Hi", "My", "Name", "Is" , "Dennis"}; 
    char **aPtr = a; 
    char ***aPtr2 = &aPtr; 
    char ***aPtr3 = &a; 

    printf("%p %c\n", a, *a); 
    printf("%p %p %c\n", aPtr, *aPtr, **aPtr); 
    printf("%p %p %p %c\n", aPtr2, *aPtr2, **aPtr2, ***aPtr2); 
    printf("%p %p %c\n", aPtr3, *aPtr3, **aPtr3); 

    return 0; 
} 

che produce l'uscita:

0xfff65578 H 
0xfff65578 0x8048648 H 
0xfff65574 0xfff65578 0x8048648 H 
0xfff65578 0x8048648 H 

EDIT: Un'altra cosa interessante è che i puntatori di funzione sono trattati allo stesso modo.&func corrisponde a func.

int add(int a, int b) { return a + b; } 
typedef int (*PFUNC)(int, int); 

PFUNC p1 = add; 
PFUNC p2 = &add; 
if (p1 == p2) 
    printf("Huh. %d, %d\n", (*p1)(1,2), p2(3, 4)); // the dereference is also optional 
2

a è l'indirizzo di un buffer di 5 ptr ed è immutabile (vale a dire un ptr fisso). Se è stato consentito

char ***aPtr2 = &a; 

poi

*aPtr2 = &a[3]; 

sarebbe effettivamente modificare l'indirizzo a (che è verboten).