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