C语言中的未定义行为

3
这个网站的最后一节中,他们提供了f(i = -1, i = -1)作为未定义行为的例子,因为在函数参数的子表达式中存在未排序的求值。但是,由于“在计算所有函数参数和函数设计者之后,在实际函数调用之前有一个序列点”,f将始终被调用为(-1,-1),而i将被赋值为-1。这种情况有可能不会发生吗?

也许该函数会改变 i(一个全局变量?) - pmg
1
也许,但这不还是定义良好的行为吗?因为最终我将在'f'内“确定地”分配值,而不是-1。 - Sourav Kannantha B
只是为了明确:函数调用内部的逗号不是序列点。函数参数的评估顺序是未指定的,因此这确实是未定义行为。 - Andrew Henle
链接的答案中有一个(稍微牵强附会的)例子,说明可能出现的问题。 - user14215102
@dratenik,鉴于今天高度流水线化的CPU实际上可以并行执行多个指令,我不认为这个例子有任何人为的痕迹。 - Andrew Henle
显示剩余3条评论
2个回答

2

......评估后有一个顺序点。

确实。评估之后,所以毫无用处。这里的问题是在顺序点之前对 i 产生了两个未排序的副作用。这是正式的未定义行为。


如果给i分配了不同的值,那么它将是未定义的,因为无法预见i的值...但在这种情况下,i始终会计算为-1..不是吗? - Sourav Kannantha B
@SouravKannanthaB 不,这个值并不重要。假设我们有一些奇特的场景,其中i是一个易失性硬件寄存器,并且每次对它的写入都会在硬件中触发某些操作。如果不明确规定,那么这段代码将写入该硬件寄存器的时间、次数和方式都是不确定的。 - Lundin
在一个更现实的例子中,比如主流的x86 PC编译器,它很可能会尝试从情况中提取一些看似有用的东西,极有可能只是传递-1这个值。但是并不能保证任何特定的行为,这只是C语言范围之外的实现质量问题。 - Lundin

1
这是未定义的行为,因为标准规定了。在修改之间没有序列点的情况下修改变量是未定义的行为。对于规则,不存在“除非两个修改设置了相同的值”的例外情况。

所以你的意思是,使用这些特定的值可能会导致预期的行为,但是使用两个不同的值的类似表达式可能会导致未定义的行为。当然... - Sourav Kannantha B
2
@SouravKannanthaB 不,它的意思是:“规则没有任何[...]例外。” - Ian Abbott

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