2015-06-01 69 views
5

所以,我在玩C指針和指針算術,因爲我對它們不是很滿意。我想出了這個代碼。關於雙指針和三指針/雙維數組

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根據GCC 4.8.3,爲什麼是不能接受的?

對不起忘了補充編譯器警告:

警告:初始化從兼容的指針類型[默認啓用]

它也許還不清楚,我想說,讓我不得不添加此鏈接:

注意註釋掉的行。

+0

「不可接受」,你是什麼意思?請包含警告或錯誤消息。 –

+3

你確定它打破了嗎? http://ideone.com/KM516t(請注意,你缺少一個分號,並重新使用'aPtr2'的名字) – mtijanic

+0

我發佈的'ideone'鏈接爲gcc-4.9.2編譯得很好。你使用什麼編譯器標誌? – mtijanic

回答

1

這來自由C對待數組和地址的方式:

int a[5]; 

a是類型int * const,真正的,這意味着你可以用它在那裏指針的預期。但是,在堆棧上,指針的空間沒有分配,只有五個整數的空間。含義a&a[0]相同。這是所有的預期,但這裏來的奇怪的部分:

a是相同的&a。這是因爲指針沒有存儲在任何地方,你不能得到它的地址。但是,C標準並沒有失敗編譯,只是說它們是相同的,所以一些算術將起作用。

但是,由於您正在做char ***aPtr2 = &a;,您實際上正在做char ***aPtr2 = a;,這就是爲什麼您會遇到段錯誤。它只是一個雙重指針,而不是三重指針。

您可以檢查在調試器中的所有值看得更清楚,或運行程序,如:

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

產生的輸出:

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

編輯:另一個有趣的事情是函數指針以相同的方式處理。&funcfunc相同。

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是一個5 ptrs緩衝區的地址,並且是不可變的(即它是一個固定的ptr)。如果你允許

char ***aPtr2 = &a; 

然後

*aPtr2 = &a[3]; 

實際上修改地址a(這是禁止的)。