1. 对字节进行取反
如果你想对一个字节的所有位进行取反(即每个位从0变为1,或从1变为0),可以使用位运算符
~。例如,如果你有一个十六进制数
0x6C(在C++中可以直接写作0x6C),你可以这样取反:#include <iostream> #include <bitset> // 用于打印二进制表示 int main() { unsigned char ten = 0x02; unsigned char byte = 0x6C; // 初始值为0x6C byte = ~byte; // 对byte的所有位进行取反 std::cout << "ten: " << std::hex << static_cast<int>(ten) << " (" << std::bitset<8>(ten) << ")" << std::endl; std::cout << "Original: " << std::hex << static_cast<int>(byte) << " (" << std::bitset<8>(byte) << ")" << std::endl; // 打印原始值和二进制表示 std::cout << "Inverted: " << std::hex << static_cast<int>(~byte) << " (" << std::bitset<8>(~byte) << ")" << std::endl; // 再次对结果取反以恢复原始值,并打印二进制表示 unsigned char temp = ten & byte; std::cout << "temp: " << std::hex << static_cast<int>(temp) << " (" << std::bitset<8>(temp) << ")" << std::endl; return 0; }输出结果:
ten: 2 (00000010) Original: 93 (10010011) Inverted: ffffff6c (01101100) temp: 2 (00000010)unsigned char temp = ten & ~0x6C; std::cout << "temp1: " << std::hex << static_cast<int>(temp) << " (" << std::bitset<8>(temp) << ")" << std::endl; 输出: ten: 2 (00000010) Original: 93 (10010011) Inverted: ffffff6c (01101100) temp1: 2 (00000000)当你再次对取反的结果使用
~操作符时,你将得到原始值。这是因为~操作符会将所有位取反。例如,对于0x6C,其取反结果为0xFFFFFF93(如果byte是unsigned char类型的话,实际上只有最低8位有意义,其余高位将被忽略),再次取反则为原始值。如果你想要看到完整的8位二进制表示,可以使用上面代码中的方法通过std::bitset<8>来打印。注意:
使用
~操作符时,确保你了解其对数据类型的影响,特别是对于无符号整型和有符号整型。在无符号整型中,所有位都被取反。而在有符号整型中,最高位(符号位)也被取反,这可能会导致数值的符号改变(从正变负或从负变正),除非你明确知道你在做什么。对于有符号整型,通常的做法是先将其转换为无符号类型再进行操作。在上面的示例中,我使用了
static_cast<int>来确保在打印时能够正确显示数值,因为直接打印无符号字符可能会导致一些混淆或错误的结果。对于演示目的,我使用了这种方式。但在实际编程中,通常不需要这样做,除非你需要查看具体的数值。直接使用无符号字符类型进行计算和操作通常是更安全的。
2. 位运算处理
C++ 中的
0xFFFFFFFF详解
0xFFFFFFFF是一个十六进制字面量,代表 8 个十六进制位(每个十六进制位 = 4 个二进制位),即 32 位的值,所有位都是 1。它在 C++ 中有多种解释,具体取决于存储类型和上下文。1. 基本含义
#include <iostream> #include <cstdint> int main() { // 0xFFFFFFFF 的字面量类型 // 在大多数平台上,它是一个 unsigned int 类型的值 std::cout << "0xFFFFFFFF 作为 unsigned int: " << std::hex << 0xFFFFFFFF << std::dec << std::endl; // ffffffff // 二进制表示:1111 1111 1111 1111 1111 1111 1111 1111 // 也就是 32 位全为 1 return 0; }
C++ 位取反(~)与异或(^)的区别
这是一个很好的问题!虽然两者都能"翻转"位,但它们的语义和使用场景完全不同。
1. 核心区别
特性 按位取反 ~按位异或 ^操作数 一元运算符(1 个操作数) 二元运算符(2 个操作数) 作用 将所有位 0→1,1→0 相同位→0,不同位→1 真值表 1→0,0→1 0^0=0, 0^1=1, 1^0=1, 1^1=0 典型用途 取反、构造掩码 翻转特定位、加密、奇偶校验 2. 真值表对比
// 按位取反(单操作数) // x: 0 1 0 1 // ~x: 1 0 1 0 // 按位异或(双操作数) // a: 0 1 0 1 // b: 0 0 1 1 // ^: 0 1 1 0 (位不同则为1,位相同则为0)
综合运用:
反向编码:0 = 已触发,1 = 未触发
reason &= ~(1 << flag)—— 经典的位清除操作uint32_t reason{0xFFFFFFFF} reason &= ~(1 << flag) —— 经典的位清除操作 等价于下述代码: uint32_t mask = ~(1 << p_flag); // 构造掩码:仅 p_flag 位为 0,其余为 1 reason &= mask; // 按位与:将 p_flag 位清 0,其余位保持不变位运算图解 假设 p_flag = 3,reason = 0xFFFFFFFF(初始哨兵值): 1 << 3 = 0x08 (二进制: 00001000) 将整数1左移3位 ~(1 << 3) = 0xF7 (二进制: 11110111) ← 掩码,第3位为0 取反 reason (0xFFFFFFFF) = 0xFFFFFFFF (二进制: 11111111 11111111 11111111 11111111) reason & 0xF7 = 0xFFFFFFF7 (二进制: 11111111 11111111 11111111 11110111) ↑ 第3位被清0,表示该原因已触发