c语言学习笔记(8)位运算符,++,–运算符的用法

C语言学习笔记(第8章)—— 位运算符 + ++ / — 自增自减运算符

建议收藏 + 手敲所有例子,这章内容是面试、嵌入式、算法竞赛的“必杀技”!

一、位运算符(6个,全部掌握)

运算符名称示例功能说明经典用途
&按位与a & b对应位都为1才为1取特定位、判断奇偶、掩码
|按位或a | b对应位有一个1就为1设置特定位
^按位异或a ^ b对应位不同为1,相同为0交换两数、加密、找只出现一次的数
~按位取反~a所有位翻转(0变1,1变0)快速得到全1掩码
<<左移a << n所有位左移n位,低位补0快速乘2、构造大数
>>右移a >> n有符号右移(带符号位扩展)
无符号右移(补0)
快速除2、提取高位

1. 位运算核心规律(背下来一辈子受用)

a ^ a = 0
a ^ 0 = a
a & 0 = 0
a & -1 = a   // -1 的补码是全1
a | 0 = a
a | -1 = -1
~0 = -1
~(-1) = 0

2. 神级应用案例(面试手撕必备)

// 1. 不使用临时变量交换两个数(异或三连)
a = a ^ b;
b = a ^ b;  // b = (a^b)^b = a
a = a ^ b;  // a = (a^b)^a = b

// 2. 判断一个数是否是2的幂(只有一个1)
n > 0 && (n & (n-1)) == 0

// 3. 找出数组中只出现一次的数字(其他都出现两次)
int singleNumber(int* nums, int size) {
    int res = 0;
    for(int i = 0; i < size; i++) {
        res ^= nums[i];   // 成对的都变成0,剩下的就是答案
    }
    return res;
}

// 4. 不用数学运算实现加法(位运算模拟)
int add(int a, int b) {
    while(b != 0) {
        int carry = (a & b) << 1;  // 进位
        a = a ^ b;                // 不带进位的和
        b = carry;
    }
    return a;
}

3. 位移运算技巧(快如闪电)

x << 1  = x * 2
x << 2  = x * 4
x << 3  = x * 8
x >> 1  = x / 2  (对正数成立,对负数取决于实现)

#define SET_BIT(x, n)   (x |= (1 << n))      // 把第n位置1
#define CLR_BIT(x, n)   (x &= ~(1 << n))     // 把第n位清0
#define TOG_BIT(x, n)   (x ^= (1 << n))      // 第n位取反
#define GET_BIT(x, n)   ((x >> n) & 1)       // 取第n位

二、++ 和 — 自增自减运算符(最容易写错的地方)

运算符名称用法示例副作用(变量最终值)
++i前置自增j = ++i;先加后用i = i + 1
i++后置自增j = i++;先用后加i = i + 1
--i前置自减j = --i;先减后用i = i – 1
i--后置自减j = i--;先用后减i = i – 1

经典陷阱题(99%的人第一次都错)

int i = 5;
printf("%d\n", i++);    // 输出 5,i变成6
printf("%d\n", ++i);    // 输出 7,i变成7

int a = 1;
int b = a++ + a++;      // 未定义行为!(Undefined Behavior)
printf("%d\n", b);      // 可能是 3、4、5,编译器说了算!

int x = 1;
int y = x++ + ++x;      // 未定义行为!不要写这种代码!

铁律:永远不要在一句话里对同一个变量使用多次 ++/–

推荐写法(清晰无歧义)

i++;           // 单独一行,最清晰
++i;

i = i + 1;     // 某些情况下更直观
i += 1;

for(int i = 0; i < 10; i++) { }   // 经典用法,没问题

三、总结口诀(背会直接升段)

位运算口诀

  • 与0清,与1保,异或换,取反最逍遥
  • 左移乘以2,右移除以2,1左移n位就是2的n次方

自增自减口诀

  • 前++先加后用,后++先用后加
  • 一句话里别把同一个变量++两次,写错就爆炸!

终极练习题(建议手敲)

// 1. 不用循环打印一个整数的二进制(位运算)
void print_binary(unsigned int n) {
    for(int i = 31; i >= 0; i--) {
        putchar((n >> i) & 1 ? '1' : '0');
    }
    putchar('\n');
}

// 2. 计算一个整数中有多少个1(布赖恩·克尼根算法)
int count_one_bits(unsigned int n) {
    int cnt = 0;
    while(n) {
        n &= (n - 1);   // 每次消掉最右边的1
        cnt++;
    }
    return cnt;
}

掌握了本章内容,你就已经超越了 80% 的 C 语言初学者!
下一章预告:指针(真正的灵魂所在),准备好了吗?

需要我出「位运算 + 自增自减 100题PDF」或者「嵌入式位操作实战手册」,直接说一声!

文章已创建 3096

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部