提问人:Blackjack55 提问时间:10/15/2019 最后编辑:LundinBlackjack55 更新时间:10/15/2019 访问量:55
引用相同地址的算术指针
Arithmetic Pointers referencing same addresses
问:
我有点难以理解以下操作:
B 是变量,Pt1 和 Pt2 指向 &B
递减是在影响之后完成的,所以按照我的逻辑,它应该是 68,但我的 IDE 给了我 69,有人可以解释一下吗?
提前致谢。
答:
2赞
Adrian Mole
10/15/2019
#1
您给出的代码创建了未定义的行为!除去指针方面,您本质上是这样做的:
B = B--;
这无法始终如一地解决,因为您正在分配 的值,然后递减 。那么,哪个给出了答案:分配还是递减?B
69
B
在您的平台/IDE 中,编译器使用“临时”变量执行了如下操作:
// Initial value of B is 69
temp = B--; // temp is 69 and B is now 68
B = temp; // B now has the value of 69!
但是,您不能依赖这种“解释”——无论是在不同的编译器上,还是在同一个编译器的不同位置使用类似的代码!
PS:顺便说一句,您应该将代码发布为文本,格式化为代码块。
评论
0赞
Lundin
10/15/2019
“那么,哪个给出了答案:分配还是递减后?”以先评估者为准。没有办法对此进行逻辑推理,因为没有理由为什么评估顺序不是确定性的,如 C++17 所示。然而,C委员会坚持认为C语言必须保持破碎,因此没有指定顺序。你需要指向标准才能回答这个问题,你不能根据逻辑推理来写答案,因为语言是不理性的。
0赞
Lundin
10/15/2019
话虽如此,诸如此类的代码当然也不是合理的。B = B--
2赞
Lundin
10/15/2019
#2
C 标准 6.5 对这种现象给出了这个隐晦的解释:
如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用同一标量的值进行值计算未排序 对象,则行为未定义。如果有多个允许的排序 子表达式的子表达式,如果这样的未排序侧,则行为是未定义的 效果发生在任何排序中。
- 在本例中,“标量对象”是指指向的原始变量。
- 在这种情况下,“值计算”是取消引用任一指针。它们指向同一个变量。
- 在这种情况下,“副作用”意味着修改变量。赋值和运算符都是副作用。
=
--
赋值运算符没有指定其操作数的计算顺序(6.5.16 “操作数的计算是未排序的”)。未指定是在 之前还是之后发生。*Pt2
*Pt1--
这意味着编译器必须一次更新同一变量两次。由于这不是一个定义明确的方案,编译器可能会生成不正确的代码。可能显示奇怪值甚至崩溃的代码。这称为未定义行为 - 一种错误,它使程序处于无法再依赖确定性行为或预测任何结果的状态。
避免这种情况的简单方法是遵循以下最佳实践规则:
切勿在同一表达式中将 ++ 或 -- 运算符与其他运算符一起使用。
上一个:通过指针修改数据
评论