2010-09-28 37 views
8

它只是發生在我身上,我不知道如何初始化一個指針從非指針值的指針在C++一個聲明:初始化指針,指針使用碳多重地址運營商或C++

int a = 1; 
int** ppa = &&a; //Does not compile 
int** ppa = &(&a); //Does not compile 
int* pa = &a; //Works but is a 
int** ppa = &pa; //Two step solution 

我錯過了什麼,這兩個陳述是唯一的方法嗎?

+3

爲什麼你認爲在這種情況下你需要一個指針指針? – SingleNegationElimination 2010-09-28 07:55:25

+0

[指針指向C指針的工作原理]可能的重複(http://stackoverflow.com/questions/897366/how-do-pointer-to-pointers-work-in-c) – 2010-09-28 07:56:56

+1

@Jens Gustedt,this不是重複的。鏈接的問題總體上是關於指針的。這個問題是關於具體情況。 – 2010-09-28 08:05:49

回答

12

如果你想有一個指針的指針,要指出必須某處內存所在的指針,所以我覺得不可能有一個「一步到位的解決方案」,因爲你需要一個你可以指向的指針變量。

(注:這句話是不是意味着是一個語言試用使用一句話:-)「點」,儘可能多)當你做對以下

14

您無法獲得臨時指針。 &a產生r值。它不允許有實際的地址。

+1

這是100%正確的,但我接受了Philip的回答,因爲它解釋了爲什麼是這樣的原因,而不是僅僅指出標準。 – 2010-09-30 05:31:52

2

你想要一個指針(稱爲PP)到一個指針(稱爲P)?

然後P必須實際存在。這意味着你必須聲明它。

當然,編譯器會在&&a上失敗 - 因爲你不能獲取地址的地址。你可以取指針的地址 - 但你必須首先聲明指針。

這樣:

int a = 1; 
int *P = &a; 
int **PP = &P; 
+1

解析器在'&& a'上失敗並不是因爲你不能獲取地址的地址,而是因爲&&是一個在聲明中此時無效的單個標記。 'int ** ppa = x &&a;'可能是一個適當類型的'x'和一個適當重載的'&&'(邪惡!)的有效初始化,但它不會是地址的地址。 – 2010-09-28 08:04:29

0

char a; 
char* b = &a; 
char** c = &b; 

首先現在存在於堆棧上。它顯然有一個內存地址(即它的堆棧位置),這是你分配給b的地址。 b現在也存在於棧中,然後你可以將它的內存地址傳遞給c。但是,您不能在沒有中間堆棧的情況下獲取值的地址,因爲如果沒有明確創建它,它就不存在。

-1

這可能會實現:

INT ** PPA = &爲(int *){&一個};

+0

嗯,不,它會創建一個臨時的 – fileoffset 2010-09-28 07:55:05

7

其他很多都是正確的:你指向指針的指針必須指向某個東西。然而,在C99可以使用compound literals欺騙:

int a = 1; 
int **ppa = &(int *){ &a }; 

複合文字只是基本未命名的對象,並具有相同的存儲規則視爲正常對象。 (但是你不能用static關鍵字給函數作用域複合文字靜態存儲持續時間)。你甚至可以將其嵌套這樣你就可以在前面的例子改寫爲單行:

int **ppa = &(int *) { &(int) { 1 } }; 
+0

這很可能是未定義的行爲,並可能在應用程序首次使用指針時崩潰。複合文字是一個臨時文字,編譯器可以重複使用這個空格,所以'* ppa'在第二行的執行過程中指向'&a',但可能指向其他任何東西。 – 2010-09-28 08:04:45

+1

@David Rodriguez:不,你錯了。複合文字將具有與'a'和'ppa'相同的存儲持續時間:當在函數外面時是靜態的,否則在關閉塊的持續時間內是自動的。見C99 6.5.2.5(6)。 – schot 2010-09-28 08:09:33

+1

你是完全正確的。我應該在跳進評論之前檢查標準......如果您在任何時候修改了答案,評論和我將把-1變成+1,它現在不允許我改變它。無論如何,根據你想要用指針做什麼,它和中間變量解決方案一樣危險。 – 2010-09-28 08:22:32

5

C++ 03 [Section 5.3.1]說

一元&操作的結果是一個指針,其操作數。操作數應該是左值或合格的ID。在第一種情況下,如果表達式的類型是「T」的結果的類型是「指針T.」

&&a&操作者不能被應用到的&a因爲結果的結果不是lvalue

又讀this線程

2

的地址是一個數字。它只有一個地址,如果它保存在一個變量中,即一個指針。所以

int *i1 = &a; 

是有道理的,但

int **i2 = &&a; 

是沒有意義的。然而,

int **i2 = &i1; 

確實有意義。合理?

+1

你的術語是錯誤的。運算符的地址*會產生一個指針,請參見[ISO03,5.3.1 expr.unary.op§2]。通常會調用指針*值*「地址」和指針*變量*「指針」,但嚴格來說,這是錯誤的。 – fredoverflow 2010-09-28 10:26:16

+0

我使用的術語是常用的。標準意義上的指針的值是任何意義上的地址,而這在任何意義上都是一個數字。把我說的另一種方式,&不產生*變量,*因此它不會產生任何地址可以採取。 – EJP 2010-09-28 10:33:55

0

當您執行類似&&a;這樣的操作時,問題是您要求提供「地址a」的地址。

這沒有意義。我們可以得到a的地址就好了,但是這並不能給我們一個我們可以接受的地址。它只是給了我們一個指針值。在該值存儲在某個地方之前,我們不能接受它的地址。

如果您有諸如2+2的代碼,結果也沒有地址。它只是價值4,但它還沒有存儲在任何地方,所以我們不能接受地址。一旦我們將它存儲到一個int變量中,我們就可以獲取該變量的地址。

基本上,問題是值和變量之間的差異。值只是一個數字(或一個字符或其他數據)。變量是存儲值的地方。一個變量有一個地址,但一個值沒有。

在C++中 - 說,它是rvalues和左值之間的差異。一個右值本質上是一個臨時值,它通常是從另一個操作返回的值(例如您的案例中的&運算符),但它尚未存儲在任何地方。

一旦你將它存儲到一個變量,你會得到一個左值,左值有一個你可以採取的地址。

所以是的,你需要兩個單獨的陳述。首先你得到地址,然後你在某處存儲該地址。然後你可以把這個「某處」的地址。

+0

您的術語是錯誤的。運算符的地址*會產生一個指針,請參見[ISO03,5.3.1 expr.unary.op§2]。通常會調用指針*值*「地址」和指針*變量*「指針」,但嚴格來說,這是錯誤的。 – fredoverflow 2010-09-28 10:25:26

+0

@Fred:夠公平的。我懷疑我會因此而陷入困境。 ;)這會教我嘗試重新定義C++語義:p – jalf 2010-09-28 10:28:28

+0

修正了一下。希望我得到最具誤導性的位。 – jalf 2010-09-28 10:30:12