目标:系统掌握 & | ^ ~ << >> 的语义与陷阱、无符号优先、掩码构造、字段打包/解包、按 2 的幂对齐、位计数/低位索引等实战技巧。

1)无符号优先(避免实现定义行为)
- 右移 >>:对有符号负数是实现定义(算术/逻辑右移不必定);
- 提议:用无符号类型做移位与掩码:uint32_t/uint64_t。
2)基本操作速查
u &= mask; // 保留
u |= mask; // 置位
u ^= mask; // 反转
u &= ~mask; // 清零
构造单比特:(UINT32_C(1) << n);风险:n >= 位宽 → 未定义行为。
3)字段打包/解包(协议友善)
// 布局: [31:29]=ver(3) [28:24]=type(5) [23:0]=len(24)
static inline uint32_t pack_hdr(uint32_t ver,uint32_t type,uint32_t len){
return ((ver & 0x7u) << 29) |
((type & 0x1Fu)<< 24) |
(len & 0xFFFFFFu);
}
static inline void unpack_hdr(uint32_t x, uint32_t *ver,uint32_t *type,uint32_t *len){
*ver = (x>>29) & 0x7u;
*type = (x>>24) & 0x1Fu;
*len = x & 0xFFFFFFu;
}
与大小端无关:我们在寄存器值上操作;跨网络请配合 htonl/ntohl。
4)对齐到 2 的幂(常用)
// 向上取整到 2^k
static inline uint32_t align_up_pow2(uint32_t x, uint32_t a){ // a 为 2 的幂
return (x + (a-1)) & ~(a-1);
}
static inline uint32_t align_down_pow2(uint32_t x, uint32_t a){
return x & ~(a-1);
}
5)位计数/最低位索引
- 可移植做法:
static inline unsigned popcount_u32(uint32_t x){
unsigned c=0; while(x){ x &= x-1; ++c; } return c;
}
static inline unsigned ctz_u32(uint32_t x){ // count trailing zeros
unsigned n=0; if(!x) return 32;
while((x & 1u)==0){ x >>= 1; ++n; } return n;
}
- 如可用编译器内建:__builtin_popcount/__builtin_ctz(GCC/Clang),MSVC:_BitScanForward。
6)位标志枚举 + 掩码工具(与第 13 讲配套)
enum Feature { F_A=1u<<0, F_B=1u<<1, F_C=1u<<2 };
typedef unsigned FeatureMask;
#define F_SET(m,f) ((m)|=(f))
#define F_CLR(m,f) ((m)&=~(f))
#define F_HAS(m,f) (((m)&(f))!=0)
7)常见坑
- 左移超位宽:1u << 32(在 32 位无定义)。
- 用有符号整型做右移。
- 忘记把常量声明为无符号:1 << n 参与提升后可能溢出。
- 用位域表达跨平台协议(布局/端序不可控)。
8)练习
- 写 mask_range(lo, hi):生成 [lo, hi] 连续 1 的掩码;
- 写 is_pow2(x) 与 next_pow2(x);
- 实现 64 位的 popcount/ctz(优先用内建)。
© 版权声明
文章版权归作者所有,未经允许请勿转载。




收藏了,感谢分享
👍👍