2016-09-03 133 views
3

我對指針和數組一個非常基本的,但困擾的問題:混淆指向數組的指針

int main() { 

    int a[5] = { 1,2,3,4,5 }; 
    int(*pa)[5] = &a; 

    std::cout << a << std::endl; 
    std::cout << &a << std::endl; 

    std::cout << pa << std::endl; 
    std::cout << (*pa) << std::endl; 

    return 0; 
} 

出人意料的是,所有四個輸出給同一個地址,像'006AF784',這意味着a == &apa == *pa。這對我沒有任何意義!

我明白當然'a'的是指針的第一個元素,同時'&a'是指針到整個數組,所以'a+1'是從'&a+1'不同。但是一個變量等於它的地址,一個指針等於指向我無法理解的內容。我想知道C和編譯器中究竟發生了什麼。

回答

1

隱式轉換和「數組衰減成指針」就在這個背後。我們畫這個數組。假設它從地址0x98開始存儲。

+———————————————————+ 
| 1 | 2 | 3 | 4 | 5 | 
+———————————————————+ 
^ 
| 
0x98 

應該清楚該數組的地址是0x98。
很明顯,它的第一個元素的地址也是0x98。

當你打印

std::cout << a << std::endl; 

a被轉換成一個指針到它的第一個元件 - 它相當於

std::cout << &a[0] << std::endl; 

如上所示,這具有相同的數值作爲指向數組的指針。

同樣地,當打印

std::cout << (*pa) << std::endl; 

*pa,作爲一個陣列,被轉換成一個指針到它的第一個元素。

+0

變量'a'可能被認爲是一個包含5個整數的對象。因此,std :: cout << a被轉換爲count <<&a [0]來打印第一個整數的地址,而std :: cout <<&a打印整個對象的地址,當然從它的第一個元素開始。 – Roy

+0

@羅伊這不僅是可能的,這是一個事實。這就是數組。 – molbdnilo

1

你幾乎回答了你自己的問題。你想知道爲什麼a,&a是相同的:指定數組的第一個表達式的計算結果爲第一個元素的指針,而另一個計算結果爲指向整個事物的指針,正如你注意的那樣。但是兩者都是相同的地址:第一個元素位於數組的基地址。那爲什麼pa一樣?爲什麼,因爲你在聲明中從&a初始化了它;它的價值從&a。和*pa是一樣的,因爲pa是一個指向數組的指針,所以*pa是數組。但是一個數組的計算結果爲指向第一個元素的指針:並且您已經在a中看到了這一點。表達式*pa指定與a相同的對象,具有相同的類型並以相同的方式評估。

1

重要的是要明白,a不是一個指針。在C的語義中,數組名可以轉換爲一個指針,但否則只是數組第一個元素地址的別名。

然後,當涉及到pa,你只是說這個指針應該是a的地址,所以當然當你打印它的值時,它應該是相同的。 當然,因爲*pa是一個數組(它的數組名稱),它只是將其第一個元素的地址 - 也就是a的地址進行別名。

+0

我認爲你的第一句話可能是OP有問題。 'a'是一個數組變量,如你所說,它可以轉換爲一個指針,但僅僅保存數組的第一個元素就是它的值。 –

+0

@ DavidC.Rankin:是的,'a'是一個數組變量。更確切地說,'a'是數組對象的名稱。但'a'不僅僅保存數組的第一個元素; 「a」的值是整個數組對象的值,由其所有元素的值組成。在大多數情況下,*表達式*'a'隱式轉換爲指針表達式,產生數組對象初始元素的地址。 –