取消引用后增量 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
实际上会在调用 printf
1.
之前更新
但是,(*p)++
会不一样;你不是增加指针,而是增加 p
指向 的东西。
1。 ++
或 --
运算符的副作用必须在下一个 序列点 之前应用,在这种特殊情况下,它发生在计算函数参数的时间之间并调用函数本身。
关于这个我收到了很多相互矛盾的答案。但正如我一直理解的那样。
当我们在 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
实际上会在调用 printf
1.
但是,(*p)++
会不一样;你不是增加指针,而是增加 p
指向 的东西。
1。
++
或 --
运算符的副作用必须在下一个 序列点 之前应用,在这种特殊情况下,它发生在计算函数参数的时间之间并调用函数本身。