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

时间:2016-03-01 21:05:38

标签: c pointers gcc operator-precedence

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

当我们在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进行了测试

4 个答案:

答案 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。