【问题标题】:What is side effect in C?C中的副作用是什么?
【发布时间】:2020-06-02 08:57:01
【问题描述】:

维基百科说:

在计算机科学中,如果某个操作、函数或表达式在其本地环境之外修改了某些状态变量值,即具有除了向操作的调用者返回一个值(主要效果)之外,还有一个可观察的效果。

但是我们如何在其本地环境之外访问一个变量,任何人都可以将这种情况,副作用,主效应和序列点解释清楚吗?

【问题讨论】:

  • 例如,函数在返回之前从其代码中修改全局变量。
  • 如果你通过引用将一个变量从一个本地作用域传递到另一个作用域,这个变量可以被改变,除非参数是 const 类型。
  • 函数内的代码驻留在该函数的范围内,而不是在全局变量所在的全局范围内。如果一个函数只返回一个值并且不修改其范围之外的任何内容,则称为纯函数。

标签: c scope side-effects sequence-points


【解决方案1】:

函数是(应该是)一个黑盒子,其中返回值或通过引用传递的变量的值应该是唯一可能根据输入参数而改变的东西。

函数在这些情况之外产生的任何其他可观察到的变化都是副作用。最著名的例子可能是printf() 函数,它除了返回写入的字符数之外,还更改标准输出的内容,这意味着更改与管道、文件或屏幕相关的一些内存缓冲区,例如实例,并且不属于函数的本地环境。

【讨论】:

    【解决方案2】:

    C 语言中没有所谓的“主效应”。

    副作用在C语言(C17 5.1.2.3/2)中的正式定义是:

    访问 volatile 对象、修改对象、修改文件或调用执行任何操作的函数 这些操作都是副作用,它们是执行环境状态的变化。

    显然,副作用是:

    • 访问 volatile 变量,或
    • 写入任何变量,
    • 或写入文件

    (其中stdout 可能被视为给定系统的文件。)

    这与确定是否/如何允许编译器优化代码 (C17 5.1.2.3/4) 相关:

    在抽象机中,所有表达式都按照语义的规定进行评估。一个实际的 实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用并且 不会产生任何需要的副作用(包括由调用函数或访问 易失性对象)。

    但在确定表达式是否具有明确定义的行为时,这也是序列点的用武之地。然而,序列点本身就是一个很大的话题,例如在此处的几个答案中进行了解释:@987654321 @

    【讨论】:

      【解决方案3】:

      状态是程序的属性,它告诉程序/函数/变量的行为。

      例如观察“i”(变量)的状态:

      int i = 0; // here state of i is only dependent on the value its holding. lets denote the time when i is having a value 0 as State A.
      i++; // i = 1, that means its no longer 0 i.e. state changed to state B
      i++ // i = 2 . State C
      i--; // i = 1, state B
      i += 0; // state B
      

      副作用: 一般来说,当有人谈论函数中的副作用时(不管是什么语言),他们谈论的是对函数参数和对象本身的更改之外的程序状态的更改。

      我喜欢可视化副作用的方式:

      ----------------------
                  \ <= side effect
                 ----------------
      

      在 C 中没有副作用的函数(我们忽略函数作为成员函数的可能性)可能如下所示:

      int stateOfP(int a, char *p)
      {
        *p = 0;
         return a+1;
      }
      

      在这种情况下,程序修改了 p 指向的内存位置,但由于 p 是参数中指向的内存位置,我们不会将其视为副作用。

      没有副作用的函数是一件好事,原因有几个。

      首先,没有副作用让编译器更容易优化函数的使用。

      其次,副作用使得证明程序的正确性变得更加困难。

      最后,当使用多线程时,尤其是在 C 程序中,副作用可能会产生不确定的结果。例如,如果两个线程在没有某种特殊锁定机制的情况下修改 C 程序中的普通全局变量,则程序的结果是未定义的。

      当一个函数有副作用时会是什么样子?像这样的:

      int a = 0;
      void stateChange(int p)
      {
        a++; // here the function is having side effects as 'a' is not its attribute
        return;
      }
      

      【讨论】:

      • 你说改变对象本身是什么意思??
      • 这里的对象状态是指函数本身的状态。
      猜你喜欢
      • 2021-01-13
      • 2021-04-27
      • 2010-11-07
      • 1970-01-01
      • 2017-04-15
      • 2011-07-21
      • 1970-01-01
      • 2010-12-21
      • 2023-04-10
      相关资源
      最近更新 更多