最可靠的是位运算 n & 1:对正、负、零均有效,不依赖符号规则,且避免 abs(INT_MIN) 溢出;非负整数用 n % 2 == 0 更易读;负数场景慎用 %,优先选 & 1。

用 % 运算符判断最直接,但要注意负数
绝大多数人第一反应是 n % 2 == 0:余数为 0 就是偶数。这在非负整数下完全可靠,但 C++ 中负数取模结果依赖于实现(C++98/03),C++11 起才规定 a % b 符号与被除数一致。也就是说:-5 % 2 是 -1,不是 1,所以 -5 % 2 == 0 为假,判断正确;但靠这个逻辑“推导奇偶”容易误以为它总是返回 0 或 1。
实操建议:
- 如果确定输入是非负整数(如数组索引、循环变量),
n % 2 == 0安全、易读、无性能问题 - 若可能为负(比如用户输入、计算结果),别只看
== 0,改用abs(n) % 2 == 0或更稳妥的位运算方案 - 编译器对
% 2常会自动优化成位操作,不必手动替换成&——可读性优先
& 1 位运算是最底层可靠的奇偶判断
整数在内存中以二进制补码存储,最低位为 1 表示奇数,为 0 表示偶数。n & 1 直接提取这一位:结果是 1(真)即奇数,0(假)即偶数。它不依赖符号规则,对正、负、零全部统一有效。
常见错误现象:
立即学习“C++免费学习笔记(深入)”;
- 写成
n & 0x1没问题,但没必要——1就是0x1,多敲字符还降低可读性 - 误用
|或^:比如n | 1永远非零,n ^ 1是翻转最低位,不是判断 - 对浮点数或指针用
& 1:编译报错,位运算是整型专属
示例:int x = -3; if (x & 1) { /* 进入,-3 是奇数 */ }
模板函数封装时,得小心类型和 constexpr
想写个通用函数?比如 is_even<t>(n)</t>,不能直接对所有 T 用 & 1——bool、char 没问题,但 unsigned long long 也没问题;真正要拦的是浮点类型和自定义类。
实操建议:
- 用
std::is_integral_v<t></t>在编译期做 SFINAE 或static_assert检查 - 想支持
constexpr(比如用于数组维度),必须用& 1,因为%在某些旧标准或复杂表达式里可能无法 constexpr 求值 - 别为性能强行泛化:对
int写死n & 1比模板调用更快,也更清晰
性能差异几乎可以忽略,但嵌入式或热循环里位运算略稳
在现代 x86/ARM 上,% 2 和 & 1 都会被编译器优化成单条指令(如 test eax, 1),实际运行时没有差别。但某些 DSP 或老款 MCU 编译器可能不优化 %,导致调用除法库函数——这时 & 1 就是硬性要求。
使用场景提示:
- 普通应用层代码:选
% 2 == 0,语义明确,维护者一眼看懂 - 内核驱动、传感器采样循环、裸机固件:优先用
& 1,避开任何潜在除法开销 - 如果用了
std::abs(n) % 2处理负数,注意abs(INT_MIN)在二进制补码下溢出(未定义行为),这时候& 1仍是唯一安全解
最常被忽略的一点:奇偶判断本身很简单,但“数从哪来”往往带坑——比如从字符串解析的 int 可能溢出,或从网络收到的字节序未转换。别只盯着 & 和 %,先确保那个 n 是你真想判断的那个数。









