C中的指针操作和运算符优先级

时间:2014-01-06 18:46:37

标签: c arrays pointers dereference operator-precedence

背景

今天刚和C人聊天,我们不同意以下情况:

int intgA[2] = { 1, 2 };
int intgB[2] = { 3, 5 };

int *intAPtr = intgA;
int *intBPtr = intgB;

所以当我们这样做时:

*intAPtr++ = *intBPtr++;

我的分析

首先:

intBPtr递增1,现在指向地址5。 然后,deference,保持值5;

intAPtr也递增1,现在指向地址2。 随后引用并且值为2;

最后:

2替换为5。

所以他们分别是:5和5。

他的分析

*intBPtr的值首先首先分配给*intAPtr

因此,它们变为:3和3。

然后*intAPtr*intBPtr都会加1。

所以,他们分别成为:4和4。

我的假设

我认为++运算符优先于*=,因此我的断言。

例如,如果我们有:

*intAPtr++; 

结果应该是2,对吗?因为我们首先递增指针然后取消引用。

那么为什么在上述情况下,正如他所声称的那样,我们首先将intBPtr的值分配给intAPtr的值并最后增加值?

在这里提出所有建议之后,我在IDE中运行了代码,结果证实了@sujin:

虽然它确认我至少在优先权方面是正确的:

那:*intAPtr++ = *intBPtr++;

intAPtr++具有更高的优先级,从而导致:intAPtr将其地址递增1。

现在指向:2的地址。

同样地:

intBPtr++也会增加1(地址)。

现在指向:地址5。

然后是*

因此两者分别取消引用(*)为2和5.

但是问题仍然存在,因为上面的分配(=)似乎没有发生。

如果确实如此,那么两者都会变成5。

期待进一步开悟。

6 个答案:

答案 0 :(得分:9)

声明

*intAPtr++ = *intBPtr++;

被解析为

*(intAPtr++) = *(intBPtr++);

并分解如下:

  • intBPtr(3)当前指向的值已分配到intAPtrintgA[0])指向的位置;
  • 指针 intAPtrintBPtr会递增。

这些事情的确切顺序是未指定;你不能依赖intBPtr intAPtr之后递增,反之亦然,也不能依赖增量之前发生的作业等。

所有这一切都完成后,intgA[0] == 3intAPtr == &intgA[1]以及intBPtr == &intgB[1]

表达式a++在增量之前计算为a 的值。

答案 1 :(得分:5)

你和另一个人都错了!

无论哪种,
1.两个指针先递增,然后进行赋值或
2.一个指针递增,然后分配发生,然后另一个指针递增或
3.首先进行赋值,然后指针递增。

但规则是,在下一个语句开始之前,必须完成一个语句的所有副作用。请记住必须使用原始值。只要使用原始值,增量就可以随时发生。

C-faq: 3.2

  

无法保证在放弃前一个值之后以及在评估表达式的任何其他部分之前立即执行增量或减量。 仅保证在表达式被视为“已完成”之前的某个时间执行更新

请阅读answer提供的Eric Lippert详细说明。

答案 2 :(得分:4)

是的,++*更紧密,但你误解了它是如何运作的。 var++增加var,但在增量之前评估为var 的值。如果你愿意的话,你可以把它想象成(var += 1, var - 1)的语法糖。

另一种思考方式是:如果它按照你认为的方式运作,那么var++++var之间就没有区别了,其中一个就不会被包括在内首先是语言。 C几乎没有裁员。

(绑定优先级 重要;例如,它意味着*var++增加变量var的值,而(*var)++增加内存中的值位于*var。)

答案 3 :(得分:3)

++运算符的主要作用是生成其操作数的值(不增加它)。副作用是增加操作数。

即使在主效应产生的值在另一个操作中使用之前执行副作用,主效果产生的值也是操作数的原始值,而不是更新的值。

*x++中,解析为*(x++)*运算符应用于主效果生成的值,因此*运算与如果评估*x。增量发生在主表达式评估之外的“侧面”,因此它不会参与确定*x++的值。

答案 4 :(得分:2)

示例代码(在linux中):

#include <stdio.h>
#include <stdlib.h>
int main() {
    int intgA[2] = { 1, 2 };
    int intgB[2] = { 3, 5 };
    int *intAPtr = intgA; //1
    int *intBPtr = intgB; //3
    *intAPtr++ = *intBPtr++;
    // *intAPtr = *intBPtr;
    // *intAPtr++ = 25; 
    printf("op: %d %d\n", *intAPtr, *intBPtr);

   return 0;
}

输出:

op: 2 5

首先将intBPtr分配给intAPtr然后增加,因为它是后增量。

答案 5 :(得分:1)

我同意John Bode的回答,以简化它 我将在代码中写下它:

   *intAptr = * intBPtr;

等于:

   *intAptr =*intBPtr 
   intAPtr+=1;
   inrBPtr+=1;

所以我们得到的是: intAPtr指向2 intBPtr指向5