优先级 | 运算符、含义 | 结合性 |
1 | [ ] 数组下标 | 从左到右 |
( )圆括号 | ||
a++ 自增 | ||
a- - 自减 | ||
2 | ++ a 自增 | 从右到左 |
- - a 自减 | ||
* 取值 | ||
&取地址 | ||
! 逻辑非 | ||
3 | = 赋值 | 从右到左 (左面三个都是双目运算符) |
+= 加后赋值 | ||
-= 减后赋值 |
1、a++:先返回值a,再执行a=a+1; (先赋值再自加)
如:int a=3; b=a++; 运算结果为: a=4; b=3;
2、++a:先执行a=a+1,再返回值a;(先自加再赋值)
如:int a=3; b=++a; 运算结果为: a=4; b=4;
在c中,++有前置和后置如 ++a;a++;,单独使用的时候是没有区别的,都是自加1,在有运算时就有区别了,前置的++是自加后才参与运算,后置的++是参与运算后在自加1。
3、a+=b;意思为a=a+b
如:a=1;b=2;a+=b; 运算结果为: a=3; b=2;
4、a+=b++;
运算过程: 先a=a+b;再b=b+1(b的值先参与运算再自加);
如:a=1;b=2;a+=b++; 运算结果为: a=3;b=3;
5、a+=++b;
运算过程: 先b=b+1;再a=a+b;(b的值先自加再参与运算);
如:a=1;b=2;a+=++b; 运算结果为: a=4;b=3;
6、前置运算:
举例:++a=++b;
执行顺序是:
a=a+1;
b=b+1;
a=b;
举例:++a=b++;
执行顺序是:
a=a+1;
a=b;
b=b+1;
7、后置运算:
举例:a++=b++;
a=b;
a=a+1;
b=b+1;
错误,因为a++是个表达式,表达式不能作为左值
现在我们来看a++的实现:
int temp;
temp=a;
a=a+1;
return temp;
因为a++返回的是编译器自动分配的临时变量temp,而这个temp并不是你程序中定义的可寻址变量的引用 ,也就是说你不能通过地址对它进行操作.(换句话说就是不能作为左值)。
而++a的实现为:
a=a+1;
return a; //printf("a=%d",a+1)
因为++a返回的是a,它是程序中定义的可寻址变量的引用,所以它可以作为左值。
a++和++a在做左值的时候有不同,那么左值它首先必须是有特定地址的才能作为左值,否则赋值就没有具体对象。再看看a++和++a。a++的意思是先复制一份临时数据出来参与周边环境的运算,再自加变量a,可见a++用来参与运算的是一份复制出来的临时数据,这个数据是临时存在而没有固定地址的,不是一个真正的变量。++a的意思是先自加变量a,再将变量放到周边环境参与运算,那么++a用来参与运算的是有具体地址的变量,所以++a是可以作为左值使用的。
在具体一点可以理解为:
a++返回一个临时变量
++a返回变量的引用
8、int a=5; ++(a++);也是错误的;
这里(a++)是先将变量a的值(5)作为整个表达式的值返回,再将a自增1(类似于a=a+1)。
所以这里++(a++);相当于++(5),a=a+1;
9、*a++是先执行++运算,再执行 *, 即指针先移动一个位置,在对移动后指针所指位置解引用取值。(根据表格优先级)
10、再回到上面的问题:
*a++=*b++;
执行顺序是:
*a;
*b;
*a=*b;
a++;
b++;
下列代码实现 strncpy 函数的功能
……
while (n-- && (*target2++ = *target1++) != '\0')
;
……