2010-09-28 49 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