运算符的学习
运算符
优先级 | 运算符 | 含义 | 运算对象的个数 | 结合方向 |
1 | ( ) | 圆括号 |
| 自左至右 |
[ ] | 下标运算符 | |||
-> | 指向结构体成员运算符 | |||
. | 结构体成员运算符 | |||
2 | ! | 逻辑非运算符 | 单目运算符 | 自右至左 |
~ | 按位取反运算符 | |||
++ | 自增运算符 | |||
-- | 自减运算符 | |||
- | 负号运算符 | |||
(类型) | 类型转换运算符 | |||
* | 指针运算符 | |||
& | 取地址符运算符 | |||
sizeof | 长度运算符 | |||
3 | * | 乘法运算符 | 双目运算符 | 自左至右 |
/ | 除法运算符 | |||
% | 求余运算符 | |||
4 | + | 加法运算符 | 双目运算符 | 自左至右 |
- | 减法运算符 | |||
5 | << | 左移运算符 | 双目运算符 | 自左至右 |
>> | 右移运算符 | |||
6 | < | 关系运算符 | 双目运算符 | 自左至右 |
<= | ||||
> | ||||
>= | ||||
7 | == | 等于运算符 | 双目运算符 | 自左至右 |
!= | 不等于运算符 | |||
8 | & | 按位与运算符 | 双目运算符 | 自左至右 |
9 | ^ | 按位异或运算符 | 双目运算符 | 自左至右 |
10 | | | 按位或运算符 | 双目运算符 | 自左至右 |
11 | && | 逻辑与运算符 | 双目运算符 | 自左至右 |
12 | || | 逻辑或运算符 | 双目运算符 | 自左至右 |
13 | ? : | 条件运算符 | 三目运算符 | 自左至右 |
14 | = | 赋值运算符 | 双目运算符 | 自右至左 |
+= | ||||
-= | ||||
*= | ||||
/= | ||||
%= | ||||
>>= | ||||
<<= | ||||
&= | ||||
^= | ||||
|= | ||||
15 | , | 逗号运算符 |
| 自左至右 |
优先级:
初等运算符 如()
单目运算符 如 !-
算数运算符(* / %在前,+ -在后)
关系运算符(> >= < <= 在前== != 在后)
逻辑运算符(除!以外, &&在前,||在后)
条件运算符
赋值运算符
逗号运算符
结合方向:除了单目运算符和赋值运算符以外其他的运算符都是自左往右的
/*
Date:2019年8月3日
Author:Zoey
Function:
(1)概念理解:优先级,操作数,结合方向——初等运算符优先等级为1,单目运算符优先等级为2
(2)只有单目运算符(只有一个操作数的运算符 例如 & 等)和赋值运算符的结合方向是自右往左的
其他运算符结合方向是自左往右的
*/
#include <stdio.h>
int main(void)
{
//概念理解
//优先级
printf("%d, %d\n", 1+2*3, (1+2)*3); //输出7, 9
//结合方向
int a = 1, b = 2, c = 3;
a = b = c; //自右向左
printf("%d\n", a); //输出3 学习目标(2)
//!(逻辑非运算符) 求该操作数的逻辑反值,如果该操作数值为真,则整个表达式值为假,否则整个表达式的值为真
printf("%d,%d,%d\n", !1, !9, !0); //输出0, 0, 1
//-(负号运算符)
printf("%d\n", 4*-3); //4*-3与4*(-3)等价,因为乘号比负号的优先级低,所以圆括号可省
return 0;
}
/*
Date:2019年8月3日
Author:Zoey
Function: 乘号,除号,取余运算符的优先级等级为3;
加号,减号的优先等级为4;
赋值运算符的优先等级为14。
*/
#include <stdio.h>
int main(void)
{
//算术运算符
printf("%d, %lf\n", 5/2, 5.0/2);
/*
输出
2, 2.500000
除号运算符的操作数如果都为整型,那么其结果也为整型,会省略掉商后面的小数部分。
如果操作数中有一个小数,那么其结果也为小数即double型
*/
int a;
printf("%d\n", a = 3.98);
/*
输出a的值为3
因为把一个浮点型数据赋给整型变量,会丢失掉小数部分。
*/
printf("%d, %d\n", 5%2, 4%2);
//5%2: 商2余1 因此输出1;4%2:商2余0,因此结果为0
// printf("%d\n", 3.0%2); //error 取余运算符两边的操作数必须为整型 否则编译会报错
printf("%d, %d, %d\n", -13%3, 13%-3, -13%23); //负整数之间的取余运算,被除数减去商乘除数的结果,输出:-1, 1, -13 需要自己能计算符带负数的取余表达式的值
//赋值运算符
int b = 1, c = 7;
printf("%d\n", b += 2); //输出b的值为3,因为b += 2和b = b+2等价
printf("%d\n", c /= 2); //输出c的值为3,因为c /= 2和c = c/2等价,此外还有-=,*=,%=等赋值运算符与之类似
// b+c = 100;
//error C2106: '=' : left operand must be l-value
//但是这种检测方法是错误的,因为VC++中我们写的是C++程序
//赋值表达式是一个常数
//那么在C++中呢,实际上a,b,c是引用(指针),那么把a=b这里会得到一个a的引用。那么这里你不理解没关系,以后学到面向对象的语言就懂这里的检测方法为什么错了。
//主要呢只说一点:C语言中,赋值表达式是一个常数而不是一个左值。视频中我讲成了“赋值表达式是一个左值”,这种说法是错误的。最后我查阅C90标准是才发现的自己讲错了
a = 1, b = 2, c = 3;
(a = b) = c;
//先将b的值赋给a ,即a = 2,再将c的值赋值给a 即a = 3
printf("%d\n", a); //赋值表达式的值是其左操作数最终的值,这个值为一个左值,所以这里会输出a的值为3
return 0;
}