我很好奇,如果我有两个指针
int *x = (int *)malloc(sizeof(int));
int *y;
我希望y指向x的地址,是
y = x;
与
相同y = &*x;
答案 0 :(得分:8)
你的问题有两个部分,值得注意的是它们都不正确:
首先,你问:
是
y = x;
同样的
y =& * x;
由于取消引用(*
)和地址(&
)运算符具有相同的precedence,因此它们将从右向左绑定,因此
y = &*x;
与:
相同y = &(*x);
是的,这将产生与y=x;
相同的效果现在,如果你有一个遵循法律规定的C兼容编译器,它将不仅有效,它将相同,这是由于C规范的第6.5.3.2节P3:
一元&运算符产生其操作数的地址。如果操作数的类型为''type'', 结果有''指向类型''的类型。
如果操作数是一元*运算符的结果, 无论是运营商还是&运算符被评估,结果就像两者都是 省略
因此,编译器将同时看到*
和&
,并完全省略它们。
在你问题的后半部分,你说:
I want y to point to the address of x
据推测,您知道这不是您正在做的事情,但您要将y
设置为指向相同的地址而不是x
。 x
当然有自己的地址,可以设置,但是你需要一个不同的变量int **y = &x;
,假设x
是一个有效的值,需要解除引用。
答案 1 :(得分:4)
它们功能等效。这实际上是一个“浅层副本”。
因此,以下作业达到了相同的最终结果:
y=x;
y=&(*x);
但是,第二个操作需要更多时间才能执行,因为您不是直接分配,而是执行间接,然后执行地址操作。无论如何,编译器可能会将其优化为y=x
,具体取决于您的系统。
编辑:
如下面的海报所示,如果你的编译器支持C标准,包括C标准的6.5.3.2 P3,那么这肯定会被优化掉,可能在代码编译之前的预处理器级别。
答案 2 :(得分:3)
根据定义,它们要么完全相同,要么几乎相同,具体取决于您正在处理的C标准版本。
在ISO C99和C11中,我们在6.5.3.2中有以下措辞(引用N1570 C11草案):
一元
&
运算符生成其操作数的地址。如果 操作数的类型为“ type ”,结果的类型为“指向 type ”的指针。如果 操作数是一元*
运算符的结果,也不是 运算符和&
运算符都被计算,结果就像是 除了对运算符的约束之外,两者都被省略了 申请,结果不是左值。
所以给出:
int *x = /* whatever */;
int *y;
这两个完全等效,即使x
是空指针:
y = x;
y = &*x;
如果没有特殊情况规则,行为将是未定义的,因为*
运算符的行为仅在其操作数是有效的非空指针时才被定义。但由于永远不会评估*
,因此此处没有行为,定义或其他行为。 (事实上,与x
不同,&*x
不是左值,这与此无关。)
在C89 / C90中,尚未添加该特例规则,因此如果&*x
为空(或其他方式),则x
的行为未定义无效)指针。大多数C99之前的编译器可能会优化掉*
和&
;请记住,可以行为的行为与未预期行为的性质正如您预期的那样。
另一方面,阅读代码的人的行为存在非常真实的差异。如果我看到y = x;
,我的行为是想“哦,这是一个普通的指针赋值。”如果我看到y = &*x;
,我的行为就是思考“为什么你这样写呢?”如果我能够这样做的话,将其改为y = x;
。
答案 3 :(得分:2)
是的,虽然第二个看起来像混淆比赛的条目。
答案 4 :(得分:2)
是的,它们是相同的,但非常复杂。
您可以通过执行以下操作来测试:
y = &(*x);
printf("%p\n", (void*)x);
printf("%p\n", (void*)y);
答案 5 :(得分:1)
据我所知,它们完全相同。如果某些编译器确实以不同方式处理它们,我会感到惊讶。
由于&
的存在,*x
根本不会被评估。因此,即使x为null,也不会导致崩溃/ seg-fault。 (您可以使用程序集进行最佳验证。)
当我们谈论组装时,不可能计算* x(值)&然后&(* x)(指针)。 因此,编译器将简单地计算* x的地址,而不计算* x的值。
我们还可以检查更复杂的案例,例如&(a[10])
它只是转换为汇编中的a+10*sizeof(a[0])
。
另一个证据是offsetof
宏,通常定义为:
#define offsetof(st, m) ((size_t)(&((st *)0)->m))
这里,它正在计算&(null_pointer->m)
,这不会导致崩溃。
答案 6 :(得分:-1)
这是一个方便的小功能,可能有所帮助。不确定您是否需要所有“包含”。
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
int main() {
int *x = (int *)malloc(sizeof(int));
int *y = x;
int *z = &*x;
//y = x;
//z = &*x;
cout << "x has type: " << typeid(x).name() << '\n'
<< "y has type: " << typeid(y).name() << '\n'
<< "z has type: " << typeid(z).name() << '\n'
<< "values are " << x <<" "<< y << " " << z << '\n';
}
我从中得到的结果是:
x has type: Pi
y has type: Pi
z has type: Pi
values are 0x1a3a010 0x1a3a010 0x1a3a010
答案是,是的,使用Ubuntu 14.10,g ++的方法完全相同