Rof*_*er4 22 c c++ undefined-behavior
拿这三个C代码片段:
1) a = b + a++
2) a = b + a; a++
3) a = b + a, a++
Run Code Online (Sandbox Code Playgroud)
每个人都知道示例1是非常糟糕的事情,并且明确地调用未定义的行为.例2没有问题.我的问题是关于示例3.逗号运算符在这种表达式中是否像分号一样工作?2和3是等价还是3和1一样未定义?
具体来说,我正在考虑这个问题free(foo), foo = bar
.这基本上与上述问题相同.我可以确定foo在重新分配之前被释放,或者这是一个明确的序列点问题吗?
我知道这两个例子都是毫无意义的,只使用分号并完成它就更有意义了.我只是出于好奇而问.
dbu*_*ush 38
案例3定义明确.
关于逗号运算符的C标准的 6.5.17节,
说明如下:
2逗号运算符的左操作数被计算为void表达式; 它的评估与右操作数之间存在一个序列点. 然后评估右操作数; 结果有它的类型和价值
C++ 11标准的第5.14节第1节有类似的语言:
用逗号分隔的一对表达式从左到右进行评估; 左表达式是丢弃值表达式. 在与右表达式相关联的每个值计算和副作用之前,对与左表达式相关联的每个值计算和副作用进行排序.结果的类型和值是右操作数的类型和值; 结果与右操作数具有相同的值类别,如果右操作数是glvalue和位域,则是一个位域.
由于序列点,a = b + a
保证a++
在表达式之前完全评估a = b + a, a++
.
关于free(foo), foo = bar
,这也保证了foo
在分配新值之前免费.
Lun*_*din 11
a = b + a, a++;
是明确定义的,但a = (b + a, a++);
可以是未定义的.
首先,运算符优先级使表达式等效(a = (b+a)), a++;
,其中+
优先级最高,后跟=
依次为,
.逗号运算符包括其左右操作数的计算之间的序列点.所以代码是无意义的,完全等同于:
a = b + a;
a++;
Run Code Online (Sandbox Code Playgroud)
这当然是明确定义的.
如果我们改为编写a = (b + a, a++);
,那么逗号运算符中的序列点将不会保存当天.因为那时表达式就等于
(void)(b + a);
a = a++;
Run Code Online (Sandbox Code Playgroud)
a = a++
未经测序,(见C11 6.5.16/3).这意味着这是未定义的行为(Per C11 6.5/2).请注意,C++ 11和C++ 14的配方错误且含糊不清.=
符的操作数从右到左排序,这仍然是明确定义的.所有这一切都假设没有发生C++运算符重载.在这种情况下,将评估重载运算符函数的参数,在调用函数之前发生一个序列点,从那里发生的事情取决于该函数的内部.
归档时间: |
|
查看次数: |
2487 次 |
最近记录: |