【问题标题】:Order of Evaluation in C OperatorsC 运算符中的求值顺序
【发布时间】:2021-07-12 20:11:27
【问题描述】:

根据 C,PostIncrement(a++) > Dereference(*) > Assignment(=) 当我在 c sn-p 下面执行这个时,

#include <stdio.h>

int main(){

    int arr[]= {1,2,3};
    int *p = a;

    *p++ = 3;

    for(int i=0;i<3;i++){
        printf("%d ",arr[i]);  
    }

}

输出: 3 2 3

但是如果我们在这个语句中应用优先顺序,

 *p++ = 3;

语句将按以下顺序进行评估:

  1. p++ 将被评估
  2. *p 将被取消引用。
  3. 然后将使用赋值运算符将 3 赋值给 *p

如果我们应用上述顺序, p 指向数组 arr 的开头,将首先递增并指向数组的第二个元素。然后第二个元素的地址将被取消引用,然后 3 将分配给第二个索引。所以我们的预期输出应该是 1 3 3 但是我得到的输出是 3 2 3。

我知道我的预期输出不正确。如果您在这种情况下解释编译器输出的评估顺序,将会很有帮助。

【问题讨论】:

  • 你的意思是int *p=arr;

标签: c pointers operator-precedence post-increment


【解决方案1】:

优先级仅确定运算符与操作数的分组 - 它不控制计算表达式的顺序。优先规则只确定

*p++ = 3;

应该解析

*(p++) = 3; // as opposed to (*p)++ = 3 or *(p++ = 3)

不是按特定顺序执行操作。

++–– 运算符具有结果副作用。后缀++的结果是操作数的当前值;副作用是增加操作数。你的表达逻辑上等同于

tmp = p;
*tmp = 3;
p = p + 1;

需要注意的是,*tmp 的分配和ptr 的更新可以以任何顺序发生,它们甚至可以交错或并行执行。

【讨论】:

    【解决方案2】:

    后自增表达式的结果是操作数在其自增之前的值。因此,尽管*p++ 中的++ 确实比* 具有更高的优先级,但后者应用于p++ 表达式的结果,正如刚才提到的,@ 的初始值987654326@.

    【讨论】:

    • 所以如果它是 ++p 那么 (++p) 将首先递增然后给出结果。如果是 (p++) 那么 p++ 会先给出 p 然后递增它对吗?
    • @Allan 实际上,是的。但是,对操作时间没有实际要求;只是p++ 表达式的值将是p++ 之前的值。
    • 不错。谢谢你。
    • @Allan 此代码 sn-p 具有未定义的行为。
    • @Allan 关于使用多个未排序的++ 操作,请参阅:Why are these constructs using pre and post-increment undefined behavior?
    【解决方案3】:

    根据 C 标准(6.5.2.4 后缀递增和递减运算符)

    2 后缀++运算符的结果是操作数的值。 作为副作用,操作数对象的值递增(即 即,将相应类型的值 1 添加到其中)。 请参阅 加法运算符和复合赋值的讨论 有关约束、类型和转换以及影响的信息 对指针的操作。结果的值计算为 在更新存储值的副作用之前排序 操作数。对于不确定顺序的函数调用, postfix ++ 的操作是单次求值。后缀++ 原子类型的对象是一个读-修改-写操作 memory_order_seq_cst 内存顺序语义。

    因此在此声明中

     *p++ = 3;
    

    表达式p++ 返回指针p 的当前值,该指针指向数组的第一个元素。取消引用的正是指向数组第一个元素的 this 指针。

    所以这个说法

     *p++ = 3;
    

    不等同于语句

    p++;
    *p = 3;
    

    【讨论】:

      【解决方案4】:

      "该语句将按以下顺序进行评估:

      p++ 将被评估 *p 将被取消引用。 那么 3 将被赋值给 *p 使用赋值运算符"

      后增量运算符不是这样工作的。您可以这样假设以便更好地理解。

      • 在计算 p++ 时,首先将其当前值存储在一个临时位置,然后进行增量。
      • 所有剩余操作都对存储在临时位置的值执行。
      • 对于后续语句,使用递增值。

      【讨论】:

      • 请注意,C 标准中没有关于实际评估顺序的规范。只是后增量表达式的结果将是其操作数的(原始)值。
      • @AdrianMole,这就是我写“你可以假设”的原因
      猜你喜欢
      • 2014-12-11
      • 1970-01-01
      • 1970-01-01
      • 2012-01-07
      • 2015-03-12
      • 1970-01-01
      • 2010-11-29
      • 2011-11-03
      • 2021-08-23
      相关资源
      最近更新 更多