【问题标题】:Is chained assignment in C/C++ undefined behavior?C/C++ 中的链式赋值是未定义的行为吗?
【发布时间】:2014-05-01 18:57:30
【问题描述】:

忽略变量的类型,像a=b=c 这样的表达式是否在 C 和 C++ 中都定义了行为?

如果是这样,谁能给我官方证据,比如引用标准吗?

附:我搜索了链式分配,但我得到的一切都是关联性,但我在 C99 标准中没有找到任何关于它的文本。也许我做错了?希望任何人都可以帮助我。

【问题讨论】:

  • 我们是否假设abc 不是同一个变量?如果它们相同,则更多intereting
  • 我认为不需要在标准中明确提及,因为赋值只是一个返回赋值结果的表达式,所以a=b=c 等价于a=(b=c),这是本质上,与a=b+c 没有什么不同。
  • a=b=c 没有任何关联性要做。它将被解释为 a=(b=c),也被解释为 b=c;a=(b==0)?1:0 。抱歉,我没有看到挖掘标准的任何理由,它在每本 c/c++ 书籍的开头。

标签: c++ c variable-assignment assignment-operator


【解决方案1】:

来自 C++ 标准

5.17 赋值和复合赋值运算符 [expr.ass] 1 赋值运算符 (=) 和复合赋值运算符 all 从右到左分组。都需要一个可修改的左值作为左值 操作数并返回一个引用左操作数的左值。结果 如果左操作数是位域,则在所有情况下都是位域。在所有 情况下,赋值是在值计算之后排序的 右操作数和左操作数,以及在计算值之前 赋值表达式。

还有一个例子

int a, b;
a = b = { 1 }; // meaning a=b=1;

来自 C 标准

6.5.16 赋值运算符 语义 3 赋值运算符将值存储在由左操作数指定的对象中。一个任务 表达式在赋值后具有左操作数的值,111) 但不是左值。赋值表达式的类型是类型 左操作数在左值转换后会有。副作用 更新左操作数的存储值的顺序是 左右操作数的值计算。评价 的操作数未排序。

如您所见,这是有区别的。在 C++ 中,赋值运算符返回 一个引用左操作数的左值,而在 C 中,它返回赋值后左操作数的值,111) 但不是左值

表示在C++中下面的代码是有效的

int a, b = 20;

( a = 10 ) = b;

在 C 语言中,编译器会发出错误。

【讨论】:

  • C/C++中的所有操作都是从右到左分组的吗?
  • @martixinwei 不,他们不是。您应该阅读每类运算符的说明。例如,具有一元运算符的表达式从右到左分组,而后缀表达式从左到右分组。
【解决方案2】:

这一切都与关联性有关。您可以将a=b=c 重写为a=(b=c)。赋值的结果 (b=c) 是最后一个赋值变量 (b) 的值。

【讨论】:

    【解决方案3】:

    在C和C++中,赋值是右结合的,也是一个表达式,所以

    a=b=c;
    

    被视为:

    a=(b=c);
    

    表达式b=c 在赋值后计算为b 中的任何内容。请注意,我之所以说“whatever”,是因为在 C++ 中可以(但不建议)提供一个赋值函数来完成赋值以外的事情!

    【讨论】:

    【解决方案4】:

    根据 C99 §6.5.16 (3):

    赋值表达式在赋值后具有左操作数的值,[...]

    连同求值的右结合性,假设非易失性abc,则意味着a = b = c等价于a = (b = c),又等价于b = c; a = b

    【讨论】:

    • 在实践中我还没有发现这完全正确。或者至少 gcc C99 实现还没有达到标准。 a = b = c;看起来等同于 b = c; a = c;。尝试使 b 成为易失变量:'a = b = c;'不生成 b 的读取。而'b = c; a = b;'写入后会重新读取 b。
    • @user377178 很好。答案是非正式地编写的,以解释语义,并假设所有读取和写入都可以重新排序甚至完全省略的本地和非易失性变量。我现在已经明确了这个假设。另一种选择是将b = c 描述为_tmp = c; b = _tmp,因此a = b = c 等同于_tmp = c; b = _tmp; a = _tmp,但为了专家级的准确性,这似乎牺牲了初学者级的清晰度。
    猜你喜欢
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    • 2015-07-30
    • 1970-01-01
    • 1970-01-01
    • 2019-05-21
    • 2018-05-03
    • 1970-01-01
    相关资源
    最近更新 更多