C变量地址的地址

12

在C语言中获取一个地址的地址(即单重间接)的唯一方式是使用一个中间变量作为双重间接的过渡吗?

例如,我有以下代码:

int a;
int b;
int *ptr_a;
int *ptr_b;
int **ptr_ptr_a;

a = 1;
ptr_a = &a;
ptr_ptr_a = &(&a);   <- compiler says no
ptr_ptr_a = &&a;     <- still compiler says no
ptr__ptr_a = &ptr_a; <- ok but needs intermediate variable

但是你可以反过来做,例如:

b = **ptr_ptr_a;     <- no intermediate variable required

例如,我不必做:

ptr_b = *ptr_ptr_b;
b = *ptr_b;
为什么这两个操作符在其功能上不对称?

1
因为指针必须指向某些内存。所以,ptr_a =&a表示ptr_a指向a。但是,&&a->没有“指针”可以指向的指针。ptr_a是堆栈上的一些内存,因此您可以将其指向。 - nothrow
没有必要把事情搞复杂:int *ptr_ptr_a = &ptr_a; 就可以。 - karlphillip
当然 - 在你指出之后就有意义了 - 非常感谢 - bph
7个回答

15

地址运算符返回一个rvalue,您不能取rvalue的地址(有关rvalues和lvalues之间差异的解释,请参见此处)。

因此,您需要将其转换为lvalue,并将其存储在变量中,然后可以获取该变量的地址。


3
好的,如果OP提出这个问题,那么RValues很可能是一个相当高级的概念,虽然这个回答准确无误。 - Roddy
@Roddy,没错,我添加了一个链接到MSDN文章,解释了这些概念。 - Frédéric Hamidi

8

也许通过一个像这样的示例内存布局更容易解释:

Var       Adr  value
---------------------
a         1000      1 
ptr_a     1004   1000 
ptr_ptr_a 1008   1004
                                               1008       1004      1008->1004->1000
You can obviously dereference ptr_ptr_a twice *ptr_ptr_a == ptr_a,  **ptr_ptr_a == 1

但变量 a 有一个地址 (1000),如果它不是指针的地址,那么地址的地址应该意味着什么?&a 是最终站点。因此,&&a 没有任何意义。

4
当你使用 '&' 时,你在请求存储在内存中的某个东西的地址。 使用两次 '&' 意味着你想要获取一个地址的地址,这是没有意义的。
顺带一提,如果你像现在这样使用中间变量,那么你会得到中间变量的地址。这意味着如果你使用两个中间变量来比较地址,它们将不同。 例如:
int a = 0;
int* p = &a;
int* q = &a;

// for now &p and &q are different

if (&p == &q)
  printf("Anormal situation");
else
  print("Ok");

这个答案有些可疑,"plop"不是一个变量,但&"plop"是有效的。 - ouah

2

无法获取某物的地址,因为地址的地址会产生歧义

您可以获取持有某物地址的某个东西的地址,并且您可能会有多个这样的出现(具有不同的值)


1

地址的地址是不存在的。你有一个盒子,上面有一个数字。那就是内存序列中盒子的编号。没有地方存储这些数字。正如你所看到的,这也会极其递归。


1

如果你稍微思考一下,你会注意到为了获取某个东西的地址,它必须在内存中。

如果你有一个变量

int a

它有一个地址。但是,如果不确定,在内存中它的地址实际上不存在,因此它不需要有一个地址。换句话说,您只能获取变量的地址。

在另一个方向上,情况会更容易。如果您有某物的地址,您可以取消引用它。如果这个“某些东西”是指针,您可以再次取消引用它。因此,上面提到的双间接自动给出。


1
简单来说,只有存储在计算机内存中的物体才能拥有地址。仅仅询问某个物体的地址并不意味着该地址会被存储在内存中。
当你有一个中间指针时,你现在将其存储在内存中,并获取其存储位置的地址。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接