算术运算符
用于处理四则运算。
+
- 正号/加
–
- 负号/减
*
- 乘法
/
- 除法
- 注意事项
- 除法运算后,得到的结果赋值给整型变量时,只取整数部分
- 除 0 是错误
%
- 取余
- 10 % 3 = 1
- 注意事项
- 对 0 取余是错误
- 10 % 0
- 不允许对小数取余
- 35 % 3.14
- 对负数取余,结果为余数的绝对值
- 10 % -3 = 1
- 对 0 取余是错误
++
a = 2; b=++a; // a=3;b=3
a = 2; b=a++; // a=3;b=2
- 前缀自增:先自增,再取值
- 后缀自增:先取值,再自增
—
a = 2; b=--a; // a=1;b=1
a = 2; b=a--; // a=1;b=2
- 前缀自减:先自减,再取值
- 后缀自减:先取值,再自减
赋值运算符
用于将表达式的值赋给变量。
=
- 赋值
+=
- 加等
-=
- 减等
*=
- 乘等
/=
- 除等
%=
- 模等
示例
a=2;b=3; // a=2;b=3;
a=0;a+=2; // a=0+2
a=5;a-=3; // a=5-3
比较运算符
用于表达式的比较,并返回一个真值或假值。
- 判等
!=
- 不等于
<
- 小于
- 大于
>=
- 大于等于
逻辑运算符
用于根据表达式的值返回真值或假值。
&&
- 逻辑与
||
- 逻辑或
!
- 逻辑非 (0 为假,非 0 为真)
类型转换
转换原则
- 示意图
- 占用内存字节数少的类型,向占用内存字节数多的类型转换,以保证精度不降低
分类
- 隐式转换
- 由编译器自动完成
- 由赋值产生的类型转换
- 小转大,没问题
- 大转小,有可能数据丢失
- 强制转换
大多数用于函数调用期间,实参给形参传值。
- 语法
(目标类型)待转换变量 (目标类型)待转换表达式
- 示例
#define _CRT_SECURE_NO_WARNING #include #include int main(void) { float price = 3.6; int weight = 4; double sum1 = (int)price * weight; double sum2 = (int)(price * weight); printf("sum1 = %lf\n", sum1); //sum1 = 12.000000 printf("sum2 = %lf\n", sum2); //sum2 = 14.000000 system("pause"); return 0; }
- 语法
运算符优先级
示意图:运算符总结
++/– 优先级
- 后缀优先级高于前缀
三目运算符 (?:)
- 表达式 1 ? 表达式 2 : 表达式 3
如果表达式 1 为真,取值表达式 2;否则,取值表达式 3 (类似于数据库中的 coalesce)。
-
结合方向:从右向左
-
加上小括号更具可读性
“`c
int m = a > b ? 69 : (a <b> 1,1 -> 0<pre><code>“`c
~(10011010)
= 01100101
“`
- 性质
- -a = ~a + 1
- 取反的另一种写法:a ^ (~0) = ~a
- 性质
- 按位与 (&)
- 全 1 为 1
(10010011) & (00111101) = (00010001)
- 性质
- n & (n -1) 的结果会消除二进制最低位的 1
- n & (n – 1) = 0 说明这个数二进制位中只有 1 个 1
- 应用
- 判断奇偶
- 奇数 & 1 1;偶数 & 1 0
- a & 1 等价于 a % 2
- 判断一个数是否是 2^n,如果 m & (m-1) 0,说明 m 是 2 的 n 次方
- 判断奇偶
- 全 1 为 1
-
按位或 (|)
- 全假为假
(10010011) | (00111101) = (10111111)
- 应用
- 可以将数字中指定的位置变为 1
-
和 1 做位异或,会把最后一位变为 1
(00 000 001) | (10 001 000) = (10 001 001)
- 全假为假
- 按位异或 (^)
- 相同为假,不同为真 (无进位相加)
(10010011) ^ (00111101) = (10101110)
- 异或运算的性质
- n ^ 0 n (置换常用); n ^ n 0 (去重常用)
-
满足交换律和结合律
- 交换律:两个数交换位置,和/积不变
“`c++
a ^ b == b ^ a;
“` -
结合律:三个数相加或相乘,其中任意两个数先加/乘,结果不变
“`c++
a ^ b ^ c == a ^ (b ^ c) == a ^ c ^ b
“`
- 交换律:两个数交换位置,和/积不变
-
自反性:a ^ b ^ b a ^ 0 a
- 应用:不用额外变量交换两个数
- 应用
- 交换两个整数
- 扩展:交换数据的三种方法
“`c++
// 按位异或 ^ -> 可以用来交换数据
void test03()
{
int num1 = 10, num2 = 5;
// 10 的二进制: 1010
// 5 的二进制: 0101<pre><code>//int temp;
//temp = num1;
//num1 = num2;
//num2 = temp;
//printf("第1种方法:num1 = %d, num2 = %d\n", num1, num2);//int sum = num1 + num2;
//num2 = sum – num2;
//num1 = sum – num1;
//printf("第2种方法:num1 = %d, num2 = %d\n", num1, num2);num1 = num1 ^ num2; // 1111
num2 = num1 ^ num2; // 1010
num1 = num1 ^ num2; // 0101
printf("第3种方法:num1 = %d, num2 = %d\n", num1, num2);
</code></pre>}
“`
- 三杯水法
- 异或运算法
- 求和法
- 扩展:交换数据的三种方法
- 加密解密
- 与一个 key 异或一次得到加密,再异或一次得到解密
- 比较两个值是否相等
- a ^ b 0 则相等
- 交换两个整数
- 相同为假,不同为真 (无进位相加)
- 位逻辑运算符与等号结合
- 位与运算符 &=
- val &= 0377 等价于 val = val & 0377
- 位或运算符 |=
- val |= 0377 相当于 val = val | 0377
- 位异或运算符 ^=
- val ^= 0377 相当于 val = val ^ 0377
- 位与运算符 &=
- 示例
#define _CRT_SECURE_NO_WARNINGS #include #include #include // 按位取反 ~ void test01() { int num = 2; // 00 000 010 <- 2 的源码 // 11 111 101 <- ~ 取反,计算机以补码形式表示,这个数就是计算结果的补码 // 11 111 100 <- 补码 -1 = 计算结果的反码 // 10 000 011 <- 计算结果的源码,首位表示负号,所以就是 -3 // -3 <- 转为十进制 printf("%d\n", ~num); // -3 } // 按位与 & void test02() { int num = 123; if ((num & 1) == 1) printf("num 是奇数\n"); // num 是奇数 else printf("num 是偶数\n"); }
移位运算符
- 左移 <<
- 每位左移 X 位,表示乘 2^X
-
移位填充
“`c
(10001010) -
右移 X 位,表示除以 2^X
-
移位填充
(10001010) >> 2 (0010010)
- 如果是无符号的值,都是用 0 填充
- 对于有符号的值,在不同的操作系统上,左边填充位不同,有的填 0,有的填充 1;默认填充 0
- 应用
- 求平均值 (右移 1 位,相当于除 2,并向下取整)
4 + (10-4) >> 1 = (10+4) / 2 = 7
- 求平均值 (右移 1 位,相当于除 2,并向下取整)
- 示例
// 移位运算符 void test04() { int num = 2; // 2 转为二进制: 00 000 010 // 左移2位: 00 001 000 // 转为源码: 00 001 000 // 转为十进制: 8 printf("num << 2 = %d\n", num << 2); // num <> 1 = %d\n", num >> 1); // num >> 1 = 4 }
sizeof 运算符
用于求字节数长度。