2013-08-05 246 views
3

如果我寫:C - 爲什麼指針指針與指向數組的指針不同?

char string[] = "some string"; 
char **ptr = &string; 
printf("%s\n",*ptr); 

不打印輸出,並給出了一個警告:warning: initialization from incompatible pointer type [enabled by default]

現在,如果我寫:

char *string = "another string"; 
char **ptr = &string; 
printf("%s\n",*ptr); 

它的工作原理沒事。

不應該string[]衰減到類似於*string的指針並工作嗎?爲什麼不呢?

+2

@JonathonReinhart:'string'是'炭[]',這將衰減到'字符*','不炭**'。 – icktoofay

回答

9

這不是衰變在這種情況下的工作原理。 See the C faq

6.12問: 由於數組引用衰變爲指針,如果arr是一個數組,什麼是arr&arr之間的區別?

答:在標準C中,&arr產生一個類型爲pointer-to-array-of-T的指針給整個數組。

所以,當你這樣做:

char string[] = "some string"; 
char **ptr = &string; 

分配失敗,因爲&string的類型是 「字符指針長度爲12的陣列」。你可以代替寫:

char (*ptr)[12] = &string; 

哪個(雖然幾乎可以肯定不是你想做什麼)讀「聲明PTR作爲一個指向12個字符數組」

如果你真的想要得到一個指針到一個指針,那麼你總是可以使用一箇中間變量:

char string[] = "some string"; 
char *ptr = string; 
char **doublepointer = &ptr; 
printf("%s",*doublepointer); 
+1

很好的解釋。 –

4

有一個名稱指針的概念,指向一個數組。你使用一個指針指向一個數組,而不是這樣做。如果你想指向一個數組的指針,試試下面的方法,你會得到所需的輸出。

char string[] = "some string"; 
char (*ptr)[]=&string; 
printf("%s",*ptr); 
0

其實如果我可以添加到提摩太的回答,char (*ptr)[12] = &string;類型的指針是相當不尋常的,因爲它是一個指針數組特定類型和大小。

讓我們看到,當我們之前,我們已經加一之後打印其地址會發生什麼:

char string[] = "some string"; 
char (*ptr)[12] = &string; 
printf("Before: %p\n", (void*)(ptr)); 
printf("After: %p\n", (void*)(ptr+1)); 

它打印:

Before: 0xbfec44e0 
After: 0xbfec44ec 

請注意,在第二種情況下,指針被移動了12塊內存。由於指針知道它所指向的類型的大小,所以它也適用於數組,而不僅僅適用於任何普通的舊類型。在我們的情況下是12。

有此here的深入解釋,那你migh想讀。

0

第一string是一個數組。其地址指向該陣列:

+-+-+-+-+-+-+-+-+-+-+-+ 
|s|o|m|e| |s|t|r|i|n|g| 
+-+-+-+-+-+-+-+-+-+-+-+ 

該數組的地址是一個指向,以及,一個數組,所以*char[]

第二string是指向其位於相同的字符串的指針(可能,但取決於實施)的只讀空間:

+------+ +-+-+-+-+-+-+-+-+-+-+-+ 
| addr | -> |s|o|m|e| |s|t|r|i|n|g| 
+------+ +-+-+-+-+-+-+-+-+-+-+-+ 

這個指針的地址是一個**char