取消引用后增量 C 时会发生什么

What happens when you dereference a postincrement C

关于这个我收到了很多相互矛盾的答案。但正如我一直理解的那样。

当我们在 C 中有一个指针并在 post 增量语句中使用它时,post 增量将始终发生在代码行解析之后。

int array[6] = {0,1,2,3,4,5};
int* p = array;
printf("%d", *p++); // This will output 0 then increment pointer to 1

输出:

0

非常简单的东西。现在,人们告诉我的信息与我自己的经历有些不一致。

// Same code as Before
int array[0] = {0,1,2,3,4,5};
int* p = array;
printf("%d", *(p++)); // Issue with this line

输出:

0

现在,当我 运行 代码的第二个版本时,结果是它将输出 0,然后递增指针。括号隐含的操作顺序似乎被违反了。但是,该站点上的其他一些答案告诉我,应该发生的正确事情是增量应该在取消引用之前发生。所以我想我的问题是:我的理解正确吗? post 增量语句总是在行尾执行吗?

附加信息:

我正在 linux mint 上用 gcc 编译,gcc 版本 ubuntu 4.8.4

我还在 debian 4.7.2 版本的 debian 上的 gcc 上测试了这个

*p++*(p++)在意思上没有区别。

这是因为后缀运算符的优先级高于一元运算符。

这两个表达式的意思是“p 递增,其先前的值被取消引用”。

如果要增加指针引用的对象,则需要通过编写 (*p)++.

来覆盖优先级

您的代码版本无法产生输出,然后然后递增p。原因是 p 参数表达式 中递增,它产生一个传递给 printf 的值。在 C 语言中,序列点恰好出现在调用函数之前。因此 p 的新值必须在 printf 执行之前就位。在调用 printf 之前无法进行输出。

现在,您必须对以上内容持保留态度。由于 p 是局部变量,因此修改它不是外部可见的效果。如果 p 的新值未在任何地方使用,则可以完全优化增量。但是假设我们在文件范围内有一个 int * volatile p;,并使用它来代替。然后表达式 printf("...", *p++) 必须在调用 printf 之前递增 p

OP 的 "The result is that it will output 0 THEN increments the pointer." 不正确。

后缀递增returns指针的值。将此值视为原始指针值的副本。指针递增,不影响复制。

The result of the postfix ++ operator is the value of the operand. As a side effect, the value of the operand object is incremented. ... C11dr 6.5.2.4 2

然后指针的副本被取消引用并且returns 0。这就是功能性事件序列。

由于递增指针和取消引用指针副本的副作用不会相互影响,因此哪个先发生是无关紧要的。编译器可能会根据自己的喜好进行优化。

"the end of the line"不涉及代码。重要的是表达式的结尾。

这是我对此的看法。让我们完全忽略 printf 函数,让事情变得更简单。

如果我们说

int i;
int p=0;
i = p++;

那么 i 将等于 0,因为 p 等于 0 但现在 p 已递增 1;所以现在 i 仍然等于 0,p 等于 1。

忽略 i 和 p 作为整数的声明,如果我们将其包装为示例 i = *(p++),则会发生相同的操作,但 i 现在包含 p 指向的值,其值为零。但是,现在p的值已经加1了。

表达式p++有一个结果(增量前p的值)和一个副作用p 的值更新为指向类型 int 的下一个对象)。

后缀 ++ 的优先级高于一元 *,因此 *p++ 已被解析为 *(p++);您会发现这两种形式之间的行为没有区别。 IOW,取消引用运算符应用于 p++ 结果 ;这条线

printf("%d", *p++);

大致相当于

printf("%d", *p);
p++;

注意 p 实际上会在调用 printf1.

之前更新

但是,(*p)++不一样;你不是增加指针,而是增加 p 指向 的东西。


1。 ++-- 运算符的副作用必须在下一个 序列点 之前应用,在这种特殊情况下,它发生在计算函数参数的时间之间并调用函数本身。