通过示例彻底理解自增运算符的两种用法(自减的用法与之类似,只不过是加1变成了减1)。
1、++i和i++的区别
如清单1(注意代码中的注释):
- #include <stdio.h>
- int main(void)
- {
- int a, b, i = 7;
- i++; //等价于i = i + 1;
- ++i; //等价于i = i + 1;
- a = i++; //等价于a = i; i = i + 1;
- b = ++i; //等价于i = i + 1; b = i;
- printf("a = %d, b = %d\n", a, b);
- return 0;
- }
例子输出结果:
- a = 9, b = 11
在例子中,第7和第8行的作用一样,仅仅是为变量i加1,这时i的值已经增加为9,接下来第10行变量a先获得i的值(即9),然后i加1,第11行变量i先再加1,然后把得到的值赋给b,所以b的值为11。
稍微复杂的例子,如清单2:
- #include <stdio.h>
- int main(void)
- {
- int a = 5;
- int *p = &a;
- int b = (*p)++; //等价于b = a++; 即b = a; a = a + 1;
- int c = ++(*p); //等价于c = ++a; 即a = a + 1; c = a;
- printf("b = %d, c = %d\n", b, c);
- printf("(*p)++ = %d, ++(*p) = %d\n", (*p)++, ++(*p));
- return 0;
- }
例子输出结果:
- b = 5, c = 7
- (*p)++ = 8, ++(*p) = 8
在这个例子中,只不过是通过*p来间接地操作a,其他关于自增运算符的用法与清单1类似。第9行的*p一定要用小括号括起来,否则含义就不一样了。而第11行的++(*p)也可以写成++*p(用GCC验证过),那是因为对操作数p来说它只有一个运算符*在计算它,所以无关乎运算符优先级和结合性的问题
值得注意的是,由于C语言没有指定函数各参数的求值顺序,所以第15行的代码是不可移植的,用不同的编译器可能会产生不同的结果(对于这个例子,GCC是先计算++(*p),后计算(*p)++,所以两者都等于8)。
2、*p++和*++p的区别
举例,如清单3:
- #include <stdio.h>
- int main(void)
- {
- int arr[] = {1, 2, 3, 4};
- int *p = arr;
- int a = *p++; //等价于a = *(p++); 即a = *p; p = p + 1;
- int b = *++p; //等价于b = *(++p); 即p = p + 1; b = *p;
- printf("a = %d, b = %d\n", a, b);
- return 0;
- }
例子输出结果:
- a = 1, b = 3
对于第8行的操作数p而言,*和++的优先级相同,但根据它们的右结合性可知,在这个表达式里可认为++的优先级高于*,即*p++等价于*(p++)。
而对于第10行的操作数p而言,它只有一个运算符++,所以先计算++p得出结果,然后间接运算。