微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C 运算符中的求值顺序

如何解决C 运算符中的求值顺序

根据C,PostIncrement(a++) > 取消引用(*) > 赋值(=) 当我在下面的 c 代码段中执行此操作时,

#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。

我知道我的预期输出不正确。如果您在这里解释编译器输出的计算顺序,将会很有帮助。

解决方法

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

*p++ = 3;

应该解析

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

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

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

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

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

,

后递增表达式的结果是操作数递增之前的值。因此,即使 ++ 中的 *p++ 确实比 * 具有更高的优先级,但后者应用于 p++ 表达式的结果,即刚刚提到的p的初始值。

,

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

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

因此在此声明中

 *p++ = 3;

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

所以这个声明

 *p++ = 3;

不等同于语句

p++;
*p = 3;
,

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

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

Post Increments 运算符不是这样工作的。为了更好地理解,您可以这样假设。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。