目录
(一)规则:不同的数据类型参与运算,需要转换为同一类型后运算
(1)短路与:&& 两边的操作数,只要左边不成立为0,直接返回假,不再校验右边。
(2)短路或:|| 两边的操作数,只要左边成立为1,直接返回真,不再校验右边。
一、数据类型之间的转换
(一)规则:不同的数据类型参与运算,需要转换为同一类型后运算
1.数值比较由小到大简单排序:
2.隐式类型转换
说明:编译系统自动完成,一般是低优先级类型向高优先级类型转换,这种被称为自动类型转换(由小到大)
语法:
大数据类型 变量 = 小数据类型变量
举例:
//案例一
char c = 'A'; //65
int num = c;
printf("%d",num); //65
//案例二
char c2 = 'A'; //65
int num2 = c2 + 22;
printf("%d",num2); //87
3.强制类型转换
说明:程序员自己实现,一般是高优先级类型向低优先级类型转换,这种被称作强制类型转化(由大到小)
语法:
小数据类型 变量名 = (小数据类型)大数据类型变量;
举例:
//案例1
int num1 = 65;
char c1 = (char)num1;
printf("%c",c1); //A
案例2
int num2 = 65;
char c2 = (char)(num2 + 32);
printf("%c",c2); //a
注意:强制类型转换过程中,可能会出现精度丢失的问题。如果大类型数据范围 <= 小类型数据范围,此时数据不会丢失,正常转换;如果大类型数据范围 > 小类型数据范围,此时丢失超出部分的数据,精度会缺失!
原则: 类型转换并不会改变原变量的类型
二、运算符
(一)算术运算符
1.单目运算符
说明:++ 、-- 、 +(正) 、-(负) 、*(解引用运算符)
(1)++i 与 i++的区别
int i = 1,int x = ++i;
:++
在前,先自加1,后运算;
int i = 1,int x = i++;
:++
在后,先运算,后自加1。
案例:
总结:分析上面的案例,我们发现,不管是++
在前,还是++
在后,计算数自身都会加1。区别在于运算的结果不一样,++
在前,先自加1,后运算;++
在后,先运算,后自加1。
(2)--i 和 i--区别
int i = 1,int x = --i;
:--
在前,先自减1,后运算;
int i = 1,int x = i--;
:--
在后,先运算,后自减1。
2.双目运算符
说明:+ - * / %
举例:
#include <stdio.h>
int main()
{
printf(3/2); // 1,为什么不是1.5,是因为是整型的运算,会直接舍弃掉小数部分
printf(3*1.0/2) // 1.5 为什么是1.5? 3*1.0=3.0转换为double类型
printf(10%3); // 1 求模运算(取余)
printf(10.0%3); // 1.0
printf(10.05%3); // error 求模运算是针对整数进行的
return 0;
}
注意:
两个整数相除的结果是整数,小数部分被舍弃。要想其结果是实数,可在分子*1.0(隐式类型转换)
求模运算(取余运算)左右两边的操作数都必须是整型。如果是类似于3.0这样的数是错误的
3.三目运算符
语法:表达式1?表达式2:表达式3
,相当于if..else..的简化版
求值顺序:
如果表达式1的值为真(1),则整个条件运算表达式的值为表达式2的值;
如果表达式1的值为假(0),则整个条件运算表达式的值为表达式3的值。
(二)关系运算符
说明:> < >= <= != ==
案例:
(1)什么是表达式?
表达式就是表达某种意思的式子。在C语言中,表达式指的是运算符连接操作数(变量、常量...)
注意:由关系运算符构成的表达式称为关系表达式,关系表达式的值为Boolean(布尔值)
非0:关系成立,为真
0:关系不成立,为假
(三)逻辑运算符
说明:&& (与) ||(或) !(非)
1.&&
:
逻辑与(且),符号两边的操作数都为真,结果才为真。举例:(5>4)&&(5-4)>1
,结果为0
,假
2.||
:
逻辑或(或),符号两边的操作数只要有一个为真,结果就为真。举例:(5>4)&&(5-4)>1
,结果为1
,真
3.!
:
逻辑反(取反),取反,非0为真,举例:!(!(5>4))
,结果为1
,真
4.惰性运算
所谓的惰性运算就是减少运输的次数。
(1)短路与:&&
两边的操作数,只要左边不成立为0
,直接返回假,不再校验右边。
(2)短路或:||
两边的操作数,只要左边成立为1
,直接返回真,不再校验右边。
(四)位运算符
1.说明:按位(bit)来进行运算操作的运算符
2.语法:~ & | ^ << >>
(1) ~:按位取反
说明:单目运算符,数据的每一个bit位取反,也就是二进制数位上的1变0,0变1
举例:
unsigned char ret = ~0x05; // 0000 0101 --> 1111 1010
(2) &:按位与
语法:a & b
说明:首先将参与计算的操作数转换为二进制,然后按照每一位进行对齐,处理结果如下:
1 & 1:1
1 & 0:0
0 & 0:0
0 & 1:0
总结:如果我们前后两个操作数对齐位置上的二进制数字都是1,其结果是1,否则结果都是0
(3) |:按位或
语法:a | b
说明:首先将参与计算的操作数转换为二进制,然后按照每一位进行对齐,处理结果如下:
1 | 1:1
1 | 0:1
0 | 0:0
0 | 1:1
总结:如果我们前后两个操作数对齐位置上的二进制数字只要有1,其结果是1,否则结果都是0
(4) ^:按位异或
语法:a ^ b
说明:首先将参与计算的操作数转换为二进制,然后按照每一位进行对齐,处理结果如下:
总结:不同为1,相同为0
(5) <<:左移,按bit位往左偏移
无符号左移:
语法:操作数 << 移动位数 (bit位)
unsigned int a = 3 << 3;
printf("%d\n",a); // 24
有符号左移:
语法:操作数 << 移动位数 (bit位)
int a = -3 << 3;
printf("%d/n",a); // -24
(6) >>:右移,按bit位往右偏移
无符号右移:
语法:操作数 >> 移动位数 (bit位)
unsigned int a = 3 >> 3;
printf("%d\n",a); // 0
有符号右移:
语法:操作数 >> 移动位数 (bit位)
int a = -3 >> 3;
printf("%d/n",a); // -1
案例1:
注意:
在进行移位运算的时候,凡是被移出去的位统统丢弃,凡是空出来的位统统补0,移位运算针对的是无符号整数;
如果非要进行有符号的移位运算,那么左移的时候,空出来的补0,右移的时候,空出来的补符号位(原码阶段)。
案例2:6818开发板图像绘制
需求:将一张BMP图片显示到开发板的LCD屏幕上
说明: 屏幕显示:BGR 图片显示:RGB
实现:RGB --> BGR
B:右移0个字节,也就是移动0位 B >> 0
R:右移2个字节,也就是移动16位 R >> 16
G:右移1个字节,也就是移动8位 G >> 8
(五)其他运算符
1.赋值运算符
包含:=
,由右 -> 左,优先级排倒数第二
int a = 4;
int num = 5+6;
2.复合赋值运算符
包含:+= -= *= /= %=
,由右 -> 左,优先级排倒数第二
int i = 1;
i += 1; // 等价于 i = i + 1
i *= 5; // 等价于 i = i * 5
3.sizeof(int)
说明:用来计算某种类型或者变量所占的字节数。(中文英文字符集问题,不标准)
4.逗号运算符(,)
说明:优先级最低,左 -> 右,由多个运算符将多个不同的式子连接起来的表达式称之为逗号表达式
语法:
(表达式1,表达式2...表达式n);
求值顺序:先求表达式1,再求表达式2,以此类推,整个逗号表达式的值为表达式n的值。
注意:
(1)逗号表达式的优先级最低
(2)运算顺序从左往右
(3)整个逗号表达式的值取决于最右边的表达式的值
举例:
int a = 5 ,b = 3;
int ret = (a>b,a++,b++,a); // 这种写法是为了减少代码量
print("%d\n",ret);