Pra*_*rav 9 c c++ undefined-behavior sequence-points
我有以下代码
int m[4]={1,2,3,4}, *y;
y=m;
*y = f(y++); // Expression A
Run Code Online (Sandbox Code Playgroud)
我的朋友告诉我,Expression A行为定义明确,但我不确定他是否正确.
根据他的功能f()介绍sequence point介于两者之间,因而行为定义明确.
有人请澄清一下.
PS:我知道我们不应该为实际目的编写这样的代码.这只是为了学习的目的.:)
Jam*_*lis 15
充其量,有问题的代码具有未指定的行为.对于赋值运算符,"操作数的评估顺序未指定"(C99§6.5.16/ 4).
如果首先计算左操作数,则结果f(y++)将存储在中m[0].如果首先计算右操作数,则结果将存储在m[1].
至于行为是否未定义,相关段落是:
在前一个和下一个序列点之间,一个对象的存储值最多只能通过表达式的评估来修改一次.此外,先前的值应只读以确定要存储的值(C99§6.5/ 2).
如果首先评估左侧,那么我们会违反第二句,因为排序是:
y在左侧读取值以取消引用它y在右侧读取值以增加它y++已完成并被y写入)在步骤1中,y读取"先前值" 但是出于"确定要存储的值"之外的目的.因此,行为确实未定义,因为一个有效的评估顺序会产生未定义的行为.
AnT*_*AnT 13
你对引入序列点的函数调用是绝对正确的.但是,该序列点不能保存您的情况.
首先考虑这个简单的例子
i = some_function(i++);
Run Code Online (Sandbox Code Playgroud)
有效吗?是的.为什么?它是有效的,因为函数引入的序列点(您正在讨论的序列点)将两个i彼此的修改分开,从而使代码有效.没有评估此表达式的顺序会导致在i没有插入序列点的情况下被修改两次.
但是,让我们回到您的变体
*y = f(y++);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,序列点也存在.但是,该语言不保证=运算符的求值顺序(意思是:语言不能保证首先评估赋值运算符的哪个操作数:左或右).编译器很可能会评估左侧的first(*y),函数参数second(y++),然后调用该函数然后执行实际的赋值.在这种潜在的情况下,前两个步骤 - 读取y和修改y- 不会被序列点分开.因此,行为是不确定的.
| 归档时间: |
|
| 查看次数: |
360 次 |
| 最近记录: |