局部变量赋值是否构成副作用?

does a local variable assignment constitute a side effect?

来自ISO/IEC9899:201x5.1.2.3程序执行2:

Accessing a volatile object, modifying an object, modifying a file, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. Evaluation of an expression in general includes both value computations and initiation of side effects. Value computation for an lvalue expression includes determining the identity of the designated object.

段落说"modifying an object"是副作用。意思是下面的代码:

int x; 
x = 1;

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

然而,根据 wikibooks 关于 C 编程

In C and more generally in computer science, a function or expression is said to have a side effect if it modifies a state outside its scope or has an observable interaction with its calling functions or the outside world. By convention, returning a value has an effect on the calling function, but this is usually not considered as a side effect.

Some side effects are:

  • Modification of a global variable or static variable
  • Modification of function arguments
  • Writing data to a display or file
  • Reading data
  • Calling other side-effecting functions

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

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

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

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

as if 规则是否编译出赋值是另一回事。也许,在书中,术语可观察的效果会更好?

So, who is right?

说到标准中的定义,就是标准。

is x = 1 really a side effect? even though it does not change anything outside it's scope?

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

or am I wrongly interpreted the standard?

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

另一方面,这本书 旨在教您 C。它的目的是让您 "feel" 了解 C 程序的行为方式。但为此,它很可能会使用口语和不精确的语言,这是可以预料的。如果这本书有好评,您不应该忽视它,但请记住,它不是 规范性 参考,与标准不同。

你的两个引述都包含副作用的定义:

C 标准:

which are changes in the state of the execution environment

C维基百科:

if it modifies a state outside its scope or has an observable interaction with its calling functions or the outside world.

它们定义了不同的事物,因此造成了混乱。虽然 x = 1 是副作用(C 标准),但它不是副作用(C Wikibook)。 C 维基教科书中的定义在 C 标准中称为 可观察的效果

C 标准倾向于给出模糊和不完整的术语定义,没有特别努力排除该术语不适用的所有内容。例如,C11 草案将对象定义为"region of data storage in the execution environment, the contents of which can represent values"。这类似于将 "automobile" 定义为 "a motorized vehicle which can transport people"。这样的定义可能有助于区分汽车和马,但不能区分汽车和公共汽车、皮卡车或露营车。

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