2015-06-01 4 views
5

Also, ich spielte mit C-Zeiger und Zeigerarithmetik, da ich mich nicht ganz mit ihnen wohl fühlen. Ich habe diesen Code entwickelt.In Bezug auf Doppel-und Dreifachzeiger/Doppel-Dimension-Arrays

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 ist nicht akzeptabel, nach gcc 4.8.3, warum?

Leider vergessen haben, Compiler-Warnung hinzuzufügen:

Warnung: Initialisierung von inkompatiblen Zeigertyp [standardmäßig aktiviert]

Es ist vielleicht nicht klar, was ich versuche zu sagen, also musste ich Fügen Sie diese Links hinzu:

Beachten Sie die auskommentierten Zeilen.

+0

Mit "nicht akzeptabel", was meinst du? Bitte fügen Sie die Warnung oder Fehlermeldung hinzu. –

+3

Bist du sicher, dass es kaputt geht? http://ideone.com/KM516t (Beachten Sie, dass Sie ein Semikolon verpassen und den Namen 'aPtr2' wiederverwenden) – mtijanic

+0

Der 'ideone'-Link, den ich gepostet habe, kompiliert ihn für gcc-4.9.2. Welche Compiler-Flags verwenden Sie? – mtijanic

Antwort

1

stammt aus dem Weg C behandelt Arrays und Adressen:

int a[5]; 

a ist vom Typ int * const, wahr, das heißt, Sie können es verwenden, wo ein Zeiger erwartet wird. Auf dem Stapel ist jedoch der Platz für den Zeiger nicht reserviert, nur der Platz für die fünf Eingänge. Bedeutung a ist das gleiche wie &a[0]. Dies ist alles erwartet, aber hier kommt der seltsame Teil:

a ist das gleiche wie &a. Dies liegt daran, dass der Zeiger nirgends gespeichert wird und Sie seine Adresse nicht erhalten können. Aber anstatt die Kompilierung zu versagen, sagt der C-Standard nur, dass sie gleich sind, also wird einige Arithmetik funktionieren.

Da Sie jedoch char ***aPtr2 = &a; tun, machen Sie effektiv char ***aPtr2 = a;, weshalb Sie einen segfault erhalten. Es ist nur ein Doppelzeiger, kein Dreifachzeiger.

Sie alle Werte im Debugger untersuchen kann es deutlicher zu sehen, oder ein Programm wie laufen:

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

, die die Ausgabe erzeugt:

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

EDIT: Eine andere interessante Sache ist, dass die Funktionszeiger auf die gleiche Weise behandelt werden.&func ist das gleiche wie 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 ist die Adresse eines Puffers von 5 ptrs und ist unveränderlich (d. H. Es ist ein fester ptr). Wenn Sie

erlaubt
char ***aPtr2 = &a; 

dann

*aPtr2 = &a[3]; 

würde ändern tatsächlich die Adresse a (was verboten ist). Diese