2011-10-27 222 views
12

好吧,我很難理解指針指向數組的指針。 考慮下面的代碼:爲什麼指向一個指針與指向數組的指針不兼容?

char s[] = "Hello, World"; 
char (*p1)[] = &s; 
char **p2 = &s; 
printf("%c\n", **p1); /* Works */ 
printf("%c\n", **p2); /* Segmentation fault */ 

爲什麼第一個printf工作,而第二個不?

從我所瞭解的's'是指向數組的第一個元素(即'H')的指針。 所以將p2聲明爲char **意味着它是一個指向char的指針。指向's'應該是合法的,因爲's'是指向char的指針。因此解除引用(即** p2)應該給出'H'。但它不!

+1

的分配沒有彙編VC++ 2010。 – Jon

+0

奇怪。它在GCC 4.4.4上正常工作。 – Meta

+0

@Meta:不在GCC 4.3.4([demo](http://ideone.com/K6D1D))或4.5.1([demo](http://ideone.com/gTGhY))... – ildjarn

回答

11

你的誤解在於s是什麼。它是而不是一個指針:它是一個數組。

現在大多數情況下,s計算結果爲指向數組的第一個元素:相當於&s[0],一個指向'H'。這裏最重要的是,在評估s時得到的指針值是一個臨時的短暫值 - 就像&s[0]一樣。

由於該指針不是永久性對象(它實際上並不存儲在s中),因此無法在其中指向指針指針。使用指針到指針,你必須有一個指針對象指向 - 例如,以下是OK:

char *p = s; 
char **p2 = &p; 

如果評估*p2,你告訴編譯器加載的東西p2指向並將其視爲指向char的指針。這很好,p2確實指向一個指向char的指針;但是當你做char **p2 = &s;時,p2指向的東西根本就不是指針 - 它是一個數組(在這種情況下,它是一個13 char s的塊)。

+0

好的。我想我現在開始明白了。 你能否澄清關於s是'暫時的,短暫的價值'的部分?每次都不是同一個地址嗎? – Meta

+1

@Meta:我的意思是,'s'計算的指針不是一個可尋址的對象,就像'a + 1'不是一樣(在標準的情況下,它不是一個左值)。 – caf

+0

@caf,如果's'不是一個可尋址的對象,那麼'&s'怎麼不是一個編譯錯誤(但是'&(a + 1)')? – Shahbaz

1

From what I understand, 's' is a pointer to the first element of the array
不,s是一個數組。它可以簡化爲一個指向數組的指針,但是直到這個時候,它纔是一個數組。指向數組的指針變成指向數組的第一個元素的指針。 (是的,這有點令人困惑。)

char (*p1)[] = &s; 這是允許的,它是一個指向數組的指針,指定了一個數組的地址。它指向了s的第一個元素。

char **p2 = &s;
這使得指針指向一個指針,並指定它的數組地址。當它指向s的第一個元素(一個char)時,它會認爲它是指向一個或多個字符的指針的指針。解引用這是未定義的行爲。 (在你的情況下,段錯誤)

證明它們是不同在於sizeof(char[1000])(1000個字符,而不是一個指針的大小回報大小),功能是這樣的:

template<int length> 
void function(char (&arr)[length]) {} 

這將編譯時給定一個數組,但不是一個指針。

1

下面是工程樣品,加上指針地址的打印輸出,使事情變得簡單看:

#include <stdio.h> 
char s[] = "Hello, World"; 
char (*p1)[] = &s; 
char *p2 = (char*)&s; 

int main(void) 
{ 
    printf("%x %x %x\n", s, p2, *p2); 
    printf("%x\n", &s); // Note that `s` and `&s` give the same value 
    printf("%x\n", &s[0]); 
    printf("%c\n", **p1); 
    printf("%c\n", *p2); 
} 
+0

我在代碼中添加了一行代碼,使其更清晰一些。 – Shahbaz

相關問題