^ : 按(二进制)位异或 -- 对应二进制位相同为0, 相异为1
//位操作符 #include <stdio.h> int main() { int a = 3; // 00000000000000000000000000000011 -- 补码(正整数的原码、反码、补码相同) int b = -5; // 10000000000000000000000000000101 -- 原码 // 11111111111111111111111111111010 -- 反码 // 11111111111111111111111111111011 -- 补码 int c = a ^ b; // ^ -- 按(二进制)位异或 -- 对应二进制位相同为0, 相异为1 // 00000000000000000000000000000011 -- a补码 // 11111111111111111111111111111011 -- b补码 // 得: // 11111111111111111111111111111000 -- 补码(两个补码计算出来的也是补码) // // 这里计算出来的结果符号位是 1 ,说明是 负整数,还要计算 反码 和 补码 // 10000000000000000000000000000111 -- 反码 // 10000000000000000000000000001000 -- 原码 printf("%d\n", c); // 所以结果是-8 return 0; }
^(按位异或) 的一些规律:
1. 变量 ^ 变量 = 0
2. 0 ^ 变量 = 变量
3. 满足交换律
(实例:)
//异或是支持交换律的 #include <stdio.h> int main() { int a = 3; int b = 5; printf("%d\n", a ^ a); // 0 (每一位都是相同的,32位全是0) printf("%d\n", a ^ 0); // a = 3 // 011 - 3 (a) // 000 - 0 // 011 -- 异或结果 :a = 3 printf("%d\n", a ^ b ^ a); // b = 5 // 011 - 3 (a) // 101 - 5 (b) // 110 -- 异或结果 // 011 - 3 (a) // 101 -- 异或结果 : b = 5 printf("%d\n", a ^ a ^ b); // b = 5 // a ^ a --> 0 // 0 ^ b --> b = 5 return 0; }
一道变态面试题:不使用临时变量,交换两个数的值
(^异或 不会造成进位,所以不会产生栈溢出,但可读性不高,不易理解)
//一道变态面试题:不使用临时变量,交换两个数的值 #include <stdio.h> int main() { int a = 3; int b = 5; printf("交换前:a=%d b=%d\n", a, b); a = a ^ b; b = a ^ b; a = a ^ b; printf("交换后:a=%d b=%d\n", a, b); return 0; }
练习:求一个整数存储在内存中的二进制中1的个数
#include <stdio.h> int main() { int input = 0; int count = 0; //统计 1 的个数 //输入 scanf("%d", &input); int i = 0; for (i = 0; i < 32; i++) { // 共32位,判断32次 int test = input & 1; //按位与1 取出32位最低位 //判断是不是1 if (test == 1) { count++; //是的话,统计加1 } //判断下一位: input >>= 1; //向右移一位,继续判断,使用循环 } //输出: printf("%d", count); return 0; }
5.赋值操作符
=: 赋值操作符 -- 可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值。
int weight = 120; //体重 weight = 89; //不满意就赋值换掉 double salary = 10000.0; salary = 20000.0 //使用赋值操作符赋值
可以连续赋值(不推荐):
int a = 10; int x = 0; int y = 20; a = x = y+1; //选择赋值 //先把 y+1 赋给 x ,再把 x 赋给 a //更好的写法: x = y + 1; a = x; //这样写更加清晰而且方便一步步调试
复合赋值符
+= : 加等于
-= : 减等于
*= : 乘等于
/= : 除等于
%= : 模等于
>>= : 右移等于
<<= : 左移等于
&= : 按位与等于
|= : 按位或等于
^= : 按位异或等于
6.单目操作符
操作符只有一个操作数
! : 逻辑反操作
(if语句、while语句中、表达式中)
- : 负值
(改变数字正负)
+ : 正值
(正数默认自带+,常省略,不常用)
& : 取地址
(应用于指针)
sizeof : 操作数的类型长度(以字节为单位)
(不是函数,是操作符;计算的是类型创建变量的大小)
~ : 对一个数的二进制按位取反
(对补码32个bit位按位取反,1变成0,0变成1,取反后还是补码,要转换为原码)
-- : 前置、后置--
(常用)
++ : 前置、后置++
(常用)
* : 间接访问操作符(解引用操作符)
(应用于指针,告诉我们哪个变量是指针变量;
解引用:通过指针变量中存放的地址,找到指向的 空间/内容 )
(类型) : 强制类型转换
sizeof 和 数组
//sizeof 和 数组 #include <stdio.h> void test1(int arr[]) //传过来的首元素指针 ,一个 int*类型 大小是 4个字节 { printf("%d\n", sizeof(arr)); } void test2(char ch[]) //传过来的首元素指针 ,一个 char*类型 大小是 4个字节 { printf("%d\n", sizeof(ch)); } int main() { //整型数组: int arr[10] = { 0 }; printf("%d\n",sizeof(arr)); //使用 数组名 //40 - 计算整个数组的大小、单位字节 printf("%d\n", sizeof(int[10])); //使用数组的字符类型,包括[]和元素个数 test1(arr); //字符数组 char ch[10] = { 0 }; printf("%d\n", sizeof(ch)); //使用 数组名 //10 -- 字符数组中 sizeof(数组名) 计算 的是 字符个数 printf("%d\n", sizeof(int[10])); //使用数组的字符类型,包括[]和元素个数 //40 -- 一个 char类型元素 是 4个字节,10个就是40 test2(ch); return 0; }
~ 按位取反的运用,结合 & (按位与) 和 | (按位或)
(将 13 的 32bit位从右往左第5位,换为 1 ,再换为 0)
//~按位取反的运用,结合 & (按位与)和 | (按位或) //将 13 的 32bit位从右往左第5位,换为 1 ,再换为 0 #include <stdio.h> int main() { int a = 13; // 00000000000000000000000000001101 - 13 的 原、反、补码 // 按位或:有1就是1 // 00000000000000000000000000010000 - 1 << 4 // 00000000000000000000000000011101 -- 29 的 原、反、补码 a |= (1 << 4); // 这样就把第五位换成了 1 , 13 变成了 29 printf("%d\n", a); // 再把第五位换成 0 // 00000000000000000000000000011101 - 29 的 原、反、补码 // 00000000000000000000000000010000 - 1 << 4 // 11111111111111111111111111101111 - ~(1 << 4) 进行按位取反 // 按位或:两个都是 1 才是 1 // 00000000000000000000000000001101 -- 13 的 原、反、补码 a &= (~(1 << 4)); printf("%d", a); return 0; }
运用 ~按位取反 实现 多组输入
//运用 ~按位取反 实现 多组输入 #include <stdio.h> int main() { int a = 0; // scanf 读取失败返回的是EOF // 假设 scanf 读取失败,返回EOF ,即 -1 // -1 的补码: // 11111111111111111111111111111111 // ~ 按位取反后: // 00000000000000000000000000000000 // 得0,条件即为假 while (~scanf("%d", &a)) { printf("%d\n", a); } return 0; }
7. 关系操作符
(不能比较字符串、自定义类型)
> : 大于
>= : 大于等于
< : 小于
<= : 小于等于
!= : 不等于(用于测试“不相等”)
== : 相等(用于测试“相等”)
(=:是赋值 ; ==:是相等)
8. 逻辑操作符
&& : 逻辑与(并且:两个为真,才为真)
|| : 逻辑或(或者:多个中一个为真,就为真)
! : 逻辑非
演示:判断闰年
//判断闰年 #include <stdio.h> int main() { int y = 0; scanf("%d", &y); //1. 能被4整除,并且不能被100整除 //2. 能被400整除是闰年 if ( ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)) { printf("闰年\n"); } else { printf("不是闰年"); } return 0; }
(下回揭晓:)
9. 条件操作符
10. 逗号表达式
11. 下标引用,函数调用和结构函数
12.表达式求值