【问题标题】:does a local variable assignment constitute a side effect?局部变量赋值是否构成副作用?
【发布时间】:2019-08-26 04:40:37
【问题描述】:

来自ISO/IEC 9899:201x 部分5.1.2.3 程序执行 段落2

访问易失性对象,修改对象,修改文件, 或调用执行任何这些操作的函数都是侧面 效果,即执行状态的变化 环境。表达式的评估通常包括 价值计算和副作用的开始。价值计算 对于左值表达式,包括确定 指定对象。

段落说“修改对象”是一个副作用。表示如下代码:

int x; 
x = 1;

有一个副作用是x = 1,因为它修改了对象x

然而,根据wikibooks 关于C 编程

在 C 和更普遍的计算机科学中,函数或表达式 如果它在其范围之外修改状态,则据说有副作用 或与其调用函数或 外面的世界。按照惯例,返回值会影响 调用函数,但这通常不被视为副作用。

一些副作用是:

  • 修改全局变量或静态变量
  • 函数参数的修改
  • 将数据写入显示器或文件
  • 读取数据
  • 调用其他副作用函数

那么,谁是对的? x = 1 真的是副作用吗?即使它没有改变其范围之外的任何东西?还是我错误地解释了标准?

【问题讨论】:

  • 我认为 wiki 很困惑,并且使用术语“副作用”来表示不可优化/外部可见的副作用。正如 Erik Postpischil 在您提供的链接中所说,表达式评估的结果是主要效果。在评估期间发生的所有写入、易失性读取和系统调用都是其副作用,一些写入(或产生它们的函数调用)理论上可以在 as-if 规则下优化。
  • 每个表达式都有一个值(除了 void 表达式)和 0 个或多个副作用。表达式x = 1 的值为1;它的副作用是将 1 分配给 x。您可以在更大的表达式中使用该值 (y = 4 - (x = 1)),但不能依赖副作用的执行顺序 (y = (x = 4) + (x = 2); /* y == 6; x == ?? */)
  • @mpg 很好的解释,现在很有意义。
  • StoryTeller’s answer 是正确的,但我要补充一点,Wikibooks 文章对 副作用 给出了不同的定义,它对这些副作用的描述可能是正确的——但是这是该术语的不同用法。也就是说,这并没有错(因为人们可以使用他们自己的定义来定义术语;C 标准无权强制其他),但它应该明确表示它使用了一些非 C 定义。值得注意的是,这篇文章说“In C”是错误的。

标签: c language-lawyer side-effects


【解决方案1】:

当 C 书籍采用 C 标准中使用的术语(例如副作用)并重新定义它们时,就会出现这些混淆。

C 中的副作用与标准中的该段落所定义的完全一样。

是的,x = 1 因此是一个副作用。

as if 规则是否编译出分配是另一回事。也许,在书中,可观察效果这个词会更好?

【讨论】:

    【解决方案2】:

    那么,谁是对的?

    当谈到标准中的定义时,它就是标准。

    x = 1 真的是副作用吗?即使它没有改变其范围之外的任何东西?

    是的,你引用的标准段落说了这么多。

    还是我错误地解释了标准?

    您理解标准段落并将其正确应用到x = 1。但是您尝试将外部口语定义应用于标准文本是错误的。 C 标准并不是要教任何人有关 C 的知识。它是一份正式文件,其唯一目的是定义 C 抽象机如何执行翻译后的程序。为此,它定义了一堆概念和术语。而已。当引用这些术语以预测 C 程序的预期行为时,仅适用标准的定义。

    另一方面,这本书确实旨在教你 C。它的目的是让你对 C 程序的行为方式有一个“感觉”。但为此,它很可能使用俗语和不精确的语言,这是意料之中的。如果这本书有很好的评论,您不应该忽视它,但请记住,它不是一个规范参考,与标准不同。

    【讨论】:

      【解决方案3】:

      你的两句话都包含了副作用的定义:

      C 标准:

      执行环境的状态变化

      C 维基书:

      如果它在其范围之外修改了一个状态,或者与它的调用函数或外部世界有可观察的交互。

      那些定义不同的东西,从而造成混乱。虽然x = 1 是副作用(C 标准),但它不是副作用(C Wikibook)。 C Wikibooks 的定义在 C 标准中称为可观察效果

      【讨论】:

        【解决方案4】:

        C 标准倾向于给出模糊和不完整的术语定义,没有特别努力排除该术语不适用的所有内容。例如,C11 草案将对象定义为“执行环境中的数据存储区域,其内容可以表示值”。这类似于将“汽车”定义为“可以载人的机动车辆”。这样的定义可能有助于区分汽车和马,但不适用于区分汽车和公共汽车、皮卡车或露营车。

        通常使用的“副作用”的概念包括操作直接范围之外的事物的概念,并且这种概念与标准实际使用该术语的方式一致,如果人们认识到出于评估表达式或子表达式的目的,该操作的“范围”将仅限于该操作的结果或生命周期与其评估绑定的事物。但是,如果标准试图以这种方式限制“副作用”一词,则必须定义副作用相对的“范围”。该标准的作者并没有这样做,而是简单地使用了更广泛的定义,并依靠读者将应用程序限制在有意义的地方。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-05
          • 2013-08-02
          • 2011-11-06
          • 2018-01-12
          相关资源
          最近更新 更多