问题描述
根据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;
该语句将按以下顺序进行评估:
- p++ 将被评估
- *p 将被取消引用。
- 然后将使用赋值运算符将 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++ 被求值时,首先,它的当前值被存储在一个临时位置,然后进行增量。
- 对存储在临时位置的值执行所有剩余操作。
- 对于后续语句,使用递增值。