当您取消引用后增量C时会发生什么
我收到了很多相互矛盾的答案。 但正如我一直理解的那样。
当我们在C中有一个指针并在后增量语句中使用它时,后增量将始终在代码行结算后发生。
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 post increment语句总是在行尾执行吗?
附加信息:
我正在使用gcc版本ubuntu 4.8.4在linux mint上编译gcc
我也在debian上使用版本debian 4.7.2在gcc上测试了这个
OP的“结果是它将输出0 THEN递增指针。” 是不正确的。
后缀增量返回指针的值。 将此值视为原始指针值的副本。 指针递增,不影响复制。
postfix ++运算符的结果是操作数的值。 作为副作用,操作数对象的值递增。 …… C11dr 6.5.2.4 2
然后取消引用指针的副本并返回0
。 这是事件的function序列。
由于递增指针和取消引用指针副本的副作用不会相互影响,因此首先出现哪一个是无关紧要的。 编译器可以根据需要进行优化。
“行尾”不涉及代码。 表达的结尾很重要。
*p++
和*(p++)
之间的含义没有区别。
这是因为后缀运算符的优先级高于一元运算符。
这两个表达式都意味着“ p
递增,其先前值被解除引用”。
如果要增加指针引用的对象,则需要通过编写(*p)++
来覆盖优先级。
没有版本的代码可以产生输出, 然后增加p
。 原因是p
在参数表达式中递增,该表达式产生一个传递给printf
的值。 在C中,序列点恰好在调用函数之前发生。 所以p
的新值必须在printf
执行之前就位。 并且在调用printf
之前不能输出。
现在,你必须带上一点点盐。 由于p
是局部变量,因此修改它不是外部可见效果。 如果p
的新值未在任何地方使用,则可以完全优化增量。 但是假设我们有一个int * volatile p;
在文件范围,并使用它。 然后表达式printf("...", *p++)
必须在调用printf
之前递增p
。
表达式p++
有一个结果 (增量前的p
值)和副作用 ( p
的值更新为指向int
类型的下一个对象)。
Postfix ++
优先级高于一元*
,因此*p++
已被解析为*(p++)
; 你会发现这两种forms之间的行为没有区别。 IOW,dereference运算符应用于p++
的结果 ; 这条线
printf("%d", *p++);
大致相当于
printf("%d", *p); p++;
需要注意的是,在调用printf
1之前, p
实际上会更新。
但是, (*p)++
会有所不同; 而不是递增指针,你正在增加p
指向的东西。
1.必须在下一个序列点之前应用++
或--
运算符的副作用,在此特定情况下,在计算函数参数和调用函数本身之间。
这是我对此的看法。 让我们完全忽略printf函数并使事情变得更简单。
如果我们说
int i; int p=0; i = p++;
那么我将等于零,因为p等于零,但现在p增加了1; 所以现在我仍然等于零,p等于1。
忽略i和p作为整数的声明,如果我们在示例中包装它, i = *(p++)
,则会发生相同的动作,但我现在包含p指向的值,其值为零。 但是,现在p的值已增加1。