告别位运算恐惧!C语言操作符详解大全
目录
一、操作符分类
1、全家福一张表
类别 | 操作符 |
---|---|
算术操作符 | +、-、*、/、% |
移位操作符 | <<、>> |
位操作符 | &、|、^ |
赋值操作符 | =、+=、-=、*= 、/=、%=、<<=、>>=、&=、|=、^= |
单目操作符 | ! ++ -- & * + - ~ sizeof (类型) |
关系操作符 | >、>=、<、<=、==、!= |
逻辑操作符 | &&、|| |
条件操作符 | ?、: |
逗号操作符 | , |
下标引用 | [] |
函数调用 | () |
在C语言中,运算符是有优先级的,在cppreference 优先级表中给出了相应的优先级顺序,若优先级相同,这时候需要看关联性决定结合顺序
2、优先级 & 关联性速查表
二、进制转换
1、十进制 ↔ 二进制
- 十进制→二进制:除 2 取余,倒着写
例:13₁₀ → 1101₂
- 二进制→十进制:按权值展开,多少位的进制就乘相应的次幂,从
0
开始
例:1101₂ = 1×2³ + 1×2² + 0×2¹ + 1×2⁰ = 13₁₀
2、二进制↔ 八进制/十六进制
目标 | 分组 | 前缀 | 例 |
---|---|---|---|
八进制 | 3 位一组 | 0 | 1101₂ → 000 110 101 → 015 |
十六进制 | 4 位一组 | 0x | 1101₂ → 0xD |
三、原码、反码、补码
内存里只有
补码
,CPU只有加法器
!
有符号整数的三种表示方法均有符号位和数值两部分2进制序列中,
最高位
是被当作符号位,其余都是数值位
0
表示正
,1
表示负
。
正整数的原、反、补码都相同。
负整数的三种表示方式各不相同。
整数 | 原码 | 反码 | 补码 |
---|---|---|---|
+5 | 0000 0101 | 同原 | 同原 |
-5 | 1000 0101 | 1111 1010 | 1111 1011 |
快速口诀:负数反码符号不动其余取反,补码=反码+1
四、移位操作符
操作数必须是整数!
移位是移动内存中的二进制位
4.1 左移操作符:<<
移位规则:左边抛弃、右边补0
int a = 10; // 0000 1010
int b = a<<1;// 0001 0100 → 20
4.2 右移操作符:>>
移位规则:分为两种(由编译器决定,通常算术右移)
1、逻辑右移:左边补
0
,右边丢弃
2、算术右移:左边补符号位
,右边丢弃
int a = -8; // 1111 1000
int b = a>>1;// 1111 1100 → -4
Tips: 操作数必须是整数;移动负数位 → 未定义行为!
五、位操作符
操作符 | 中文 | 口诀 | 用途 |
---|---|---|---|
& | 按位与 | 有 0 则 0 | 清 0 / 取掩码 |
| | 按位或 | 有 1 则 1 | 置 1 |
^ | 异或 | 同 0 异 1 | 翻转 / 无 tmp 交换 |
~ | 取反 | 0↔1 | 得到全 1 或全 0 |
1、经典面试:无临时变量交换
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
a = a^b;
b = a^b;//b=a
a = a^b;//a=b
printf("a = %d b = %d\n", a, b);
return 0;
}
2、整数在内存中的二进制中 1 的个数
#include <stdio.h>
int main()
{
int num = -1;
int i = 0;
int count = 0;//计数
while(num)
{
count++;
num = num&(num-1);
}
printf("⼆进制中1的个数 = %d\n",count);
return 0;
}
3、二进制第 k 位 置为1/0
13的2进制序列: 00000000000000000000000000001101
将第5位置为1后:00000000000000000000000000011101
将第5位再置为0:00000000000000000000000000001101
#include <stdio.h>
int main()
{
int a = 13;
a = a | (1<<4);
printf("a = %d\n", a);
a = a & ~(1<<4);
printf("a = %d\n", a);
return 0;
}
六、单目操作符
操作符 | 含义 |
---|---|
! | 逻辑反 |
++ -- | 自增/自减 |
& * | 取地址/解引用 |
+ - | 正负号 |
~ | 按位取反 |
sizeof | 求字节数 |
(类型) | 强制类型转换 |
七、括号表达式
规则:从左到右依次执行,整个表达式的值 = 最后一个
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式
c是多少?
1、a > b → 1 > 2 → 逻辑值 0(结果被丢弃)
2、a = b + 10 → a = 2 + 10 → a = 12
3、a → 取表达式值 12(丢弃)
4、b = a + 1 → b = 12 + 1 → b = 13,整个逗号表达式的值就是13
八、下标引用[]、函数调用()
1、下标引用 [ ]
int arr[10];//创建数组
arr[9] = 10;//实⽤下标引⽤操作符。
[ ]的两个操作数是arr和9。
2、函数调用 ( )
接受⼀个或者多个操作数:第⼀个操作数是函数名,剩余的操作数就是传递给函数的参数。
#include <stdio.h>
void test1()
{
printf("hehe\n");
}
void test2(const char *str)
{
printf("%s\n", str);
}
int main()
{
test1(); //这⾥的()就是作为函数调⽤操作符。
test2("hello bit.");//这⾥的()就是函数调⽤操作符。
return 0;
}