5.6 位运算与字节序

本篇学习按位与、或、异或、移位和字节序的基础规则,并能用掩码处理标志位数据。

位运算与字节序

概念说明

位运算是直接对整数的二进制位进行操作。 它常用于标志位管理、权限控制、协议解析、硬件寄存器操作和某些性能敏感场景。

字节序讨论的则是“多字节数据在内存中按什么顺序存放”。 最常见的两种是:

  • 大端序:高位字节放在低地址。
  • 小端序:低位字节放在低地址。

只有当你真正把一个多字节对象拆成字节去看,或者要和网络、文件、外设打交道时,字节序问题才会变得重要。

语法/规则

  1. 常见位运算符有 &|^~<<>>
  2. & 常用于保留某些位,| 常用于设置某些位,^ 常用于翻转某些位。
  3. 位运算通常更适合搭配无符号整数使用,避免有符号移位带来的歧义。
  4. 左移和右移的位数必须合理,移位过大或对负数做不当移位都可能有风险。
  5. 处理标志位时,最好为每个掩码取有语义的名字,而不是直接写裸数字。
  6. 字节序不会影响一个整数按整数方式使用时的值,但会影响把它按字节解释时的顺序。
  7. 网络协议和跨平台二进制文件通常需要明确规定字节序,不能默认所有环境都和自己机器一样。

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>

enum {
    FLAG_READ = 1 << 0,
    FLAG_WRITE = 1 << 1,
    FLAG_EXEC = 1 << 2
};

int main(void) {
    unsigned int flags = 0;
    unsigned int value = 1;
    unsigned char *bytes = (unsigned char *)&value;

    flags |= FLAG_READ;
    flags |= FLAG_WRITE;

    printf("can_read = %u\n", (flags & FLAG_READ) != 0);
    printf("can_write = %u\n", (flags & FLAG_WRITE) != 0);
    printf("can_exec = %u\n", (flags & FLAG_EXEC) != 0);
    printf("endianness = %s\n", bytes[0] == 1 ? "little" : "big");
    return 0;
}

输出结果:

1
2
3
4
can_read = 1
can_write = 1
can_exec = 0
endianness = little

endianness 这一行在常见的 x86/x64 平台上通常会输出 little。 如果换到大端机器上,结果就可能不同,这正是字节序相关代码需要注意的平台差异。

常见错误

  1. 把位运算符 &| 和逻辑运算符 &&|| 混为一谈。
  2. 对有符号整数做复杂移位操作,却没有意识到结果可能受实现影响。
  3. 使用裸数字掩码,例如 flags |= 4,导致代码语义不清晰。
  4. 只在本机测试过二进制格式,就默认所有平台的字节顺序都和当前机器一致。
  5. 以为字节序会影响“整数本身的数学值”,却没区分“按对象使用”和“按字节解释”这两种场景。
本文禁止转载
使用 Hugo 构建
主题 StackJimmy 设计 由 Hobin 魔改
最近构建时间:2026-04-17 19:07:48 CST
载入天数...载入时分秒...
发表了 1 篇文章 · 发表了 152 篇笔记 · 总计 18 万 0 千字