序列点在c

命令性编程中的一个顺序点定义了计算机程序执行过程中的任何点,在此点上可确保先前评估的所有副作用都已执行,并且后续评估的副作用尚未执行。

这是什么意思? 有人可以用简单的话来解释吗?


当发生顺序点时,它基本上意味着您保证以前的所有操作都已完成。

在没有插入序列点的情况下更改变量两次是未定义行为的一个示例。

例如, i = i++; 是不确定的,因为对i的两次更改之间没有顺序点。

维基百科列出了C和C ++标准中的序列点,尽管最终列表应始终取自ISO标准。 从C99附录C:


以下是5.1.2.3中描述的顺序点:

  • 在对参数进行评估之后调用函数(6.5.2.2)。
  • 以下运算符的第一个操作数的结尾:逻辑AND &&(6.5.13); 逻辑OR || (6.5.14); 有条件? (6.5.15); 逗号(6.5.17)。
  • 完整申报人的结尾:申报人(6.7.5);
  • 完整表达式的结尾:初始值(6.7.8); 表达式语句(6.8.3)中的表达式; 选择语句的控制表达式(if或switch)(6.8.4); 一个while或do语句的控制表达式(6.8.5); for语句的每个表达式(6.8.5.3); 返回语句中的表达式(6.8.6.4)。
  • 紧接在库函数返回之前(7.1.4)。
  • 在与每个格式化输入/输出函数转换说明符(7.19.6,7.24.2)相关的操作之后。
  • 紧接在每次调用比较函数之前和之后,以及任何对比较函数的调用和作为参数传递给该调用的对象的任何移动(7.20.5)之间。

  • C11的措词有所改变。 它似乎打破了三元运算符并增加了更多的细节:


    以下是5.1.2.3中描述的顺序点:

  • 函数指示符和函数调用中实际参数的评估与实际调用之间。 (6.5.2.2)。
  • 在以下操作符的第一个和第二个操作数的评估之间:逻辑AND &&(6.5.13); 逻辑OR || (6.5.14); 逗号(6.5.17)。
  • 在有条件的?:操作符的第一个操作数的评估和第二个和第三个操作数的评估(6.5.15)之间。
  • 完整申报人的结尾:申报人(6.7.6);
  • 完整表达式的评估和下一个要评估的完整表达式之间。 以下是完整表达式:初始值(6.7.9); 表达式语句(6.8.3)中的表达式; 选择语句的控制表达式(if或switch)(6.8.4); 一个while或do语句的控制表达式(6.8.5); for语句的每个表达式(6.8.5.3); 返回语句中的表达式(6.8.6.4)。
  • 紧接在库函数返回之前(7.1.4)。
  • 在与每个格式化的输入/输出函数转换说明符(7.21.6,7.28.2)相关的操作之后。
  • 紧接在每次调用比较函数之前和紧接之后,以及任何对比较函数的调用和作为参数传递给该调用的对象的任何移动(7.22.5)之间。

  • 关于序列点的一个重要事项是它们不是全局的,而应该被看作是一组局部约束。 例如,在声明中

    a = f1(x++) + f2(y++);
    

    在x ++的评估和对f1的调用之间有一个顺序点,在y ++的评估和对f2的调用之间有另一个顺序点。 但是,不能保证在调用f2之前或之后x是否增加,也不能保证在调用x之前或之后y是​​否增加。 如果f1改变了y或者f2改变了x,结果将是未定义的(编译器生成的代码例如读取x和y,增加x,调用f1,检查y与先前读取的值是否合理,以及 - if它发生了变化 - 继续寻找并摧毁所有Barney视频和商品;我不认为任何真正的编译器生成的代码实际上会这样做,唉,但它将在标准下允许)。


    用一个例子来展开paxdiablo的回答。

    假设声明

    x = i++ * ++j;
    

    有三个副作用:将i * (j+1)的结果分配给x,将i加1,并将j加1。 未指定应用副作用的顺序; i和j可以在被评估之后立即增加,或者直到两者都被评估之后但在x被分配之前它们才可以被递增,或者直到x被分配之后它们才可以被递增。

    序列点是应用了所有副作用(x,i和j都已更新)的点,无论它们的应用顺序如何。

    链接地址: http://www.djcxy.com/p/73273.html

    上一篇: sequence points in c

    下一篇: Can the Gradle Eclipse Plugin attach source jar files to local jar dependencies