一个简单变量i和*(&i)之间的区别是什么?

7
我有以下的C程序:
int main()
{
    int i = 5;
    printf("Simple value of i = %d", i);
    printf("\nPointer value of i = %d", *(&i));
    return 0;
}

两个printf()都会打印相同的东西,即5。据我理解,&用于地址值,*用于获取该地址上的值。

我的问题是:如果可以通过简单的i变量实现相同的效果,为什么我们需要*(&i)呢?


1
解除引用一个引用不会产生任何效果。 - Jean-François Fabre
14
“为什么我们需要*(&i)?”谁说你需要这样做? - user694733
@Jean-FrançoisFabre它会做一些事情,至少是解除引用和引用;-) 但我知道你的意思:-) ... - sjsam
在我看来,一个 OP 无意中发现了一个有趣的话题并没有什么不妥。 - Bathsheba
2
需要注意的是,虽然在C语言中它等价(除了Bathsheba提到的副作用),但在C++中它不一定相同,因为operator*可以被重载。 - Konrad Rudolph
显示剩余2条评论
2个回答

7
我的问题是,为什么我们需要 *(&i) ,如果可以用简单的 i 变量实现同样的效果?
好吧,你不需要它。
表达式 *(&i) 等价于 i 。 6.5.3.2地址和间接操作符说:
一元运算符 * 表示间接。如果操作数指向函数,则结果是函数指示器;如果指向对象,则结果是指定对象的左值设计器。如果操作数具有“类型指针”,则结果具有“类型”。如果将无效值分配给指针,则一元 * 运算符的行为未定义。102)
还有脚注:
因此,&*E 等价于 E(即使 E 是空指针),&(E1[E2]) 等价于 ((E1)+(E2))。[..]
C标准允许编译器对代码进行任何转换,只要可观察行为(参见:5.1.2.3程序执行)相同即可。 因此,该语句为:
printf("\nPointer value of i = %d", *(&i));

理论上可以转换为:

printf("\nPointer value of i = %d", i);

通过编译器而不违反C标准。


6

*(&i) 几乎与 i 完全相同。

编译器可以将其优化掉,但请注意,如果取地址的副作用存在,则不允许这样做(例如,它不能仅存储在 CPU 寄存器中)。


3
谢谢!你希望我能详细解释一下副作用的事情吗?是否与volatile或类似的东西有关?很抱歉,我需要更多上下文才能理解这个问题的完整意思。"副作用"通常是指函数或代码对系统状态、变量或参数进行的修改或操作。而"volatile"是一种关键字,用于标记变量在编译器优化时应该被特别处理以防止出现未定义行为。如果你能提供更多信息,我会尽力回答你的问题。 - Jean-François Fabre
我正在费尽心思地构思一个例子,但目前很不成功。 - Bathsheba
5
我找不到关于标准的相关信息。取地址可能会防止寄存器存储,但我找不到优化&本身被限制的证据。 - user694733
@user694733 的区别在于,如果 i 没有被初始化,在使用 i 时行为将是未定义的,而 *(&i) 只会得到一个不确定的值,据我所知,这本身并不是 UB,与 J.2 所说的相反,除非 int 具有陷阱表示。这个问题埋藏在 6.3.2.1§2 的末尾:“如果 lvalue 指定了具有自动存储期的对象,该对象可以用寄存器存储类声明[...],并且该对象未初始化[...],则行为未定义。” - Virgile

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