【问题标题】:why "f = f++" is unsafe in c?为什么“f = f++”在 c 中是不安全的?
【发布时间】:2010-12-14 01:43:37
【问题描述】:

我从this website 中了解到“副作用”:

但还是不明白为什么f = f++ 被认为是不安全的?

谁能解释一下?

【问题讨论】:

  • 重复(虽然如果你不知道为什么,这不是很明显)stackoverflow.com/questions/1678519/difference-between-i-and-i
  • 还有一个问题,为什么“++i++”是非法的,但是搜索不到!
  • 这个问题明确地询问为什么这个构造是不安全的。您引用的问题的代码无效因为此构造不安全。两个不同的完全有效的问题。
  • 是的,这就是我没有投票关闭的原因 - 但也值得阅读其他线程。

标签: c types


【解决方案1】:

来自standard

6.5 (2) 如果标量对象的副作用相对于同一标量对象的不同副作用或使用相同标量的值的值计算是无序的 对象,行为未定义。如果有多个允许的排序 表达式的子表达式,如果这样一个未排序的一面,则行为未定义 效果发生在任何顺序中。74)

74) 本段呈现未定义的语句表达式,例如

我=++我+1; a[i++] = i;

同时允许

我 = 我 + 1; a[i] = i;

【讨论】:

    【解决方案2】:

    我支持亚瑟在这方面的回答。尽管后自增运算符(即 f++)的实现令人困惑,但它并不被认为是不安全的。你应该首先了解编译器是如何解释它的。它是在遇到句子终止(;)之后增加f还是在使用f的值之后立即增加。

    【讨论】:

    • 它是 undefined,在 C 标准的意义上。这不是“您必须知道编译器做什么”的情况。编译器可以做任何事情,包括给 f 一个不符合你认为它必须生成的原子指令的任何顺序的值。
    【解决方案3】:

    问题是Sequence Points。这个语句中有两个操作没有顺序点,所以语句没有定义顺序,是先赋值还是递增?

    没有什么说它不安全,它只是未定义,这意味着不同的实现可能有不同的结果,或者它可能会格式化你的硬盘...

    【讨论】:

    • 我认为大多数人会认为格式化驱动器是f = f++ 的不安全后果。虽然我认为大多数人说“不安全”并不意味着它可能会破坏某些东西,但你不能依赖它会做什么。
    • C 和 C++ 标准自始至终都非常明确地使用术语“未定义行为”,特别是在详细说明序列点执行顺序的部分中。我只是使用夸张来强调 unsafe 和 undefined 之间的区别。
    • 事实上它没有,它只是指定未定义。想想 NULL 和 0 之间的区别(显然不是在 C++ 中)。零是一个值,NULL 是缺少一个值。未定义意味着 anything 可能会导致;是的,包括不安全的东西,但不一定。
    【解决方案4】:

    您提供的(cleaned up) link 的文章给出了答案。 “C 几乎不保证副作用会在单个表达式中以可预测的顺序发生。”这意味着您不知道 = 和 ++ 将以什么顺序出现。它依赖于编译器。

    如果您通过该文章的链接访问同一站点上有关 sequence points 的文章,您会发现编译器可以优化将寄存器中的值写回变量的内容和时间。

    【讨论】:

    • 再澄清一点——它不仅仅是依赖于编译器。编译器可以做的事情可能根本没有意义 - 甚至到同一语句的 2 个实例(f 具有相同的起始值)可能会产生完全不同的结果。
    【解决方案5】:

    在同一语句中使用xx++(或++x)在C 中是未定义的行为。编译器可以随意做任何事情:或者在之前增加x做任务,或者在那之后。使用 Ólafur 的代码,它可能会产生 f == 5f == 6,具体取决于您的编译器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-06
      • 1970-01-01
      • 1970-01-01
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      • 2017-01-11
      相关资源
      最近更新 更多