现在的位置: 首页 > 综合 > 正文

运算符优先级及结合顺序随笔

2012年09月23日 ⁄ 综合 ⁄ 共 1431字 ⁄ 字号 评论关闭

运算符优先级及结合顺序随笔

  最近在网上看到一段开源代码中有一个关于链表操作的代码,其中有一行如下:

--pNode->next;

  看到这段代码,我一时想不起这些运算符的结合顺序是什么样子了,于是开始查找资料并写了下面的测试程序:

 1   // test operator priority
 2     typedef struct
 3     {
 4         int* next;
 5     } SturctA;
 6     
 7     int a[] = {0, 1, 2, 3 };
 8     int b = 4;
 9     SturctA temp1[2];
10     SturctA *pTemp1 = &temp1[0];
11     int val1 = 0, val2 = 0, val3 = 0;
12     
13     temp1[0].next = &a[2];
14     temp1[1].next = &b;
15     
16     val1 = *--pTemp1->next;   // equals to *(--(pTemp1->next)); after operation val1 = 1, pTemp1 = &temp1[0]
17     NSLog(@"val1 value: %d", val1);
18     
19     val2 = *--pTemp1++->next; // equals to *(--(pTemp1->next)), then pTemp1++; after operation val2 = 0, pTemp1 = &temp1[1]
20     NSLog(@"val2 value: %d", val2);
21     
22     val3 = *pTemp1->next;
23     NSLog(@"val3 value: %d", val3);

  这段代码主要作用是验证前++、--,后++、--,以及->,*的优先级和结合顺序。

  程序中第2到5行,首先定义了一个结构体,该结构体中有一个指向int型的指针。第9行定义了一个结构体数组temp1[2],紧接着在第10行定义一个指向结构体数组第0个元素的指针pTemp1。13,14两行分别对数组temp1的两个结构体的next成员变量赋初值。最后16到23行对以上提到的四种的运算符进行了几种组合,并打印测试结果。

  下面我们分别看一下几种运算符组合的具体情况:

  1. 第16行代码,改行包含了前--,->以及*运算符。结合顺序是首先pTemp1->next,然后在对拿到的next进行前--的操作,最后再取出--运算以后的指针所指向的数值。根据分析我们可以得到val1 = 1的结果。
  2. 第19行代码,在前面执行的基础上(前面的执行已经修改了next指针的指向)进行了前--,后++,->以及*操作。结合顺序是首先pTemp1进行后++的操作(注:后++操作的运算符优先级最高,但不会影响本次执行),然后在和->next结合获得next的值(指向int的指针),接着再对该指针进行前--操作,最后对再取出--运算以后的指针所指向的数值。根据分析我们可以得到val2 = 0的结果(需要考虑到执行完第16行,pTemp1->next已经指向a[1]的地址)
  3. 第22行代码,在前面执行的基础上,对pTemp1的后++操作进行了验证,可以明显的看出此时pTemp1已经指向结构体数组的第1个元素了。

  上述代码只是为了验证运算符的优先级问题,日常的代码中还是尽量避免这样写,特别是不要想19行那样,建议最好加上“()”,例如19行的代码就可以修改为下面这样:

  val2 = *(--((pTemp1++)->next)); 

  总之如果不清楚优先级和结合顺序,就多加一些“()”,这样自己看起来清晰,也方面后面维护代码的同事。

抱歉!评论已关闭.