美文网首页C语言程序员
C语言编程笔记丨为什么f(i = -1, i = -1)是未定义

C语言编程笔记丨为什么f(i = -1, i = -1)是未定义

作者: 1cbd7f94d3ea | 来源:发表于2019-04-01 13:18 被阅读20次

    最近在读order of evaluation violations,其中的一个例子使我很困惑。

    1)如果对一个标量对象的副作用相对于对这个标量对象的另一个副作用是无序的,那么这是未定义行为。

    //代码片段

    f(i=-1,i=-1);//undefined behavior 未定义行为

    在这段代码中,很明显 i 是一个标量对象。

    算术类型(3.9.1),枚举类型,指针类型,指针成员类型(3.9.2),空指针类型和被const或volatile修饰的类型(3.9.3)等统称为标量类型。

    从这句话中我看不出上面那句代码有什么分歧的地方。我认为不论第一个参数还是第二个参数先执行,i最终都是-1,并且两个参数的值都是-1。

    有人能解释清楚这些吗?

    最佳答案:

    既然运算是无序的,也就不能说分配任务的指令不能交错执行。也许会选择最佳的方式去运行,由CPU的架构来决定。引用下面这句话来说明:

    如果A在B之前是无序的并且B在A之前是无序的,那么存在两种可能性:

    (1)预估A和B是无序的:它们可能以任意的顺序运行并且可能会重叠(在一个线程的执行中,编译器可能会交错组织包含A和B的CPU指令)。

    (2)预估A和B是无法确定的顺序:它们可能以任意顺序运行但是一定不会重叠。或者A在B执行之前完成或者B在A执行之前完成。下一次执行同样的语句时,执行的顺序有可能是相反的。

    假设运算执行后,把-1存进一个内存地址,就这个行为自身而言,这似乎并不会引发任何问题。但是如果一个指令和另一个指令交错执行操作同一个内存地址,你不能说编译器不会把这些指令优化成一个独立的具有同样效果的指令集,这样就会出错了。

    例如,假想把内存清零然后再递减是最高效的。现在开始值是-1,然后就是:

    f(i=-1,i=-1)

    也许会变成:

    clear i //清空 i

    clear i //清空 i

    decr i //递减 i

    decr i //递减 i

    现在i是-2。

    这也许是一个假的例子,但可能是真的。

    相关文章

      网友评论

        本文标题:C语言编程笔记丨为什么f(i = -1, i = -1)是未定义

        本文链接:https://www.haomeiwen.com/subject/chnjbqtx.html