代码之家  ›  专栏  ›  技术社区  ›  Alok Save

关于序列点的解释

  •  8
  • Alok Save  · 技术社区  · 15 年前

    最近,我看到很多关于输出的问题被问到,一些疯狂但语法上允许的代码语句,比如 i = ++i + 1 和 i=(i,i++,i)+1; . Sequence points . 坦率地说,我对序列点几乎一无所知,我只是想知道不知道在某种程度上是否是一个障碍。有人能解释一下 序列点 ,或者如果可能,指向解释该概念的资源。另外,花时间了解这个概念/理论是否值得?

    5 回复  |  直到 15 年前
        1
  •  5
  •   Chris Becke    15 年前

    我能想到的最简单的答案是:

    C++是用抽象机器来定义的。在抽象机上执行的程序的输出只根据执行“副作用”的顺序来定义。副作用定义为对IO库函数的调用,以及对标记为volatile的变量的更改。

    允许C++编译器在内部做任何事情来优化代码,但是它们不能改变写入到易失性变量和IO调用的顺序。

    在内部 序列点可以重新排序。

    这就是为什么理解它们很重要。如果没有这种理解,你对c++程序是什么(以及它如何被agreessive编译器优化)的基本理解是有缺陷的。

        3
  •  2
  •   aschepler    15 年前

    序列点的确切技术细节会变得毛茸茸的,是的。但遵循这些准则几乎解决了所有实际问题:

    • 如果表达式修改值,则在修改和 这个价值的其他用途。
    • 如果您不确定一个值的两个用法是否由一个序列点分隔,请将代码分解为更多语句。

    = , += 等等,还有 ++x , x++ , --x x-- 语法。(通常是这些递增/递减的表达式,有些人试图变得聪明,最终陷入麻烦。)

    幸运的是,在大多数“预期”的地方都有序列点:

    • 在每个陈述或声明的结尾。
    • 在内置的 && 和 || 操作员。
    • ? 在三元表达式中。
    • 在内置的 , 逗号运算符。(在中最常见的情况,例如。 for (a=0, b=0; a<m && b<n; ++a, ++b) 不 逗号运算符和是 不 序列点。

    超载 operator&& , operator|| ,和 operator, 不要引起序列点。这一事实可能带来的意外是通常不鼓励超载的原因之一。

        4
  •  1
  •   Mark Byers    15 年前

    值得一提的是,序列点的存在是因为如果你不知道它们,你可以很容易地编写代码,这些代码看起来在测试中运行良好,但实际上是未定义的,当你在另一台计算机上运行或使用不同的编译选项时,它们可能会失败。特别是如果你以写作为例 x++ 作为一个更大表达式的一部分,它还包括 x 你很容易遇到麻烦。

    我认为没有必要完全学习所有的规则——但是你需要知道什么时候需要检查规范,或者更好的是——什么时候重写你的代码使之成为这样,如果一个更简单的设计也能工作的话,你就不用依赖序列点规则了。

        5
  •  0
  •   yingted Amit    15 年前
    int n,n_squared;
    for(n=n_squared=0;n<100;n_squared+=n+ ++n)
     printf("%i squared might or might not be %i\n",n,n_squared);
    

    ... 并不总是做你认为会做的事。这会使调试变得很痛苦。