二进制字面量以0b或0b开头,后接0和1;c++14起支持数字分隔符',仅限字面量内部两数字间;空格非法,大小写不敏感但建议统一小写b;需注意跨平台编译器版本兼容性。

二进制字面量怎么写?0b开头但别漏掉小写 b
从 C++14 开始支持二进制字面量,语法是 0b 或 0B 开头,后面跟 0 和 1。大小写敏感——0B1010 合法,0b1010 也合法,但 0B1010 和 0b1010 是等价的;而 0B 写成 0B 就不行,必须是连续两个字符。
常见错误是误写成 0x 风格(比如 0b10101010 写成 0b1010 1010 中间加空格)——这会直接编译失败,空格不被允许。
-
int x = 0b1100'0011;✅(带分隔符,C++14 起支持) -
int y = 0b1100 0011;❌(空格非法,报错:error: invalid digit ' ' in binary constant) -
int z = 0B1100'0011;✅(B大写也行,但风格建议统一用小写b)
数字分隔符 ' 能用在哪些地方?只限字面量内部
' 是 C++14 引入的“数字分隔符”,作用纯属提升可读性,编译器完全忽略它。但它有严格限制:只能出现在字面量内部、两个数字之间(或基数前缀后、第一个数字前),不能在开头、结尾、小数点旁、指数符号旁。
典型误用是想给变量名或宏加下划线式分隔,比如 int flag_0b1010'1010 —— 这里 ' 不起作用,因为不在字面量中;又或者写成 0b'1010'1010,开头单引号直接触发语法错误。
立即学习“C++免费学习笔记(深入)”;
-
auto mask = 0b1100'0011'1010'0101;✅(清晰划分字节) -
double pi = 3.1415'9265'3589;✅(小数部分也可用) -
long long ns = 1'000'000'000;✅(十进制大数更易数位) -
int bad = 0b1010';❌(结尾单引号,报错:error: expected unqualified-id) -
int also_bad = 0b'1010;❌(开头单引号,解析失败)
和十六进制/八进制混用时要注意什么?分隔符不改变进制含义
分隔符本身不参与进制判断,0x、0b、0(八进制)这些前缀才决定解释方式。但人眼容易因分隔位置产生误解,尤其当混合使用不同进制字面量做位运算时。
比如 0b1111'0000 & 0xFF 看起来对齐,实际没问题;但若写成 0b1111'0000 & 0xff,小写 ff 在某些老编译器(如旧版 MSVC)可能触发警告,虽然标准允许小写,但团队规范常要求统一为大写。
-
0b1010'1010 == 0xAA✅(值相等,但类型推导可能不同:前者是int,后者是int,无隐式问题) -
0b1010'1010 == 0252✅(八进制0252也是 170,但可读性差,不推荐) -
uint8_t flag = 0b1010'1010;✅(显式类型 + 分隔符,安全) -
char c = 0b1010'1010;⚠️(可能溢出,char通常有符号,最高位为 1 会变成负数)
跨平台兼容性与编译器支持底线
所有主流现代编译器(GCC 4.9+、Clang 3.4+、MSVC 2015+)都完整支持 0b 和 '。但如果你的项目还要兼容 GCC 4.8 或更早版本,就得禁用——它们只支持 C++11,默认不认 0b,且分隔符会直接报错。
检查方法很简单:在 CI 或本地跑 g++ -std=c++14 -x c++ -E /dev/null 看是否能过预处理;或者用 static_assert 捕获:
static_assert(0b1010'1010 == 170, "binary literal broken");
如果构建失败,说明编译器没开 C++14 或版本太低。这时候要么升级工具链,要么改用宏封装(如 #define MASK_8BIT 0xAA),但会损失类型信息和调试体验。
真正容易被忽略的是:分隔符在模板推导和 constexpr 计算中完全透明,但它会让预处理器宏展开变复杂——比如 #define VAL 0b1010'1010 在某些宏拼接场景下可能意外触发 tokenization 错误,遇到就换行或加括号。










