(原文链接:https://abseil.io/tips/175 译者:clangpp@gmail.com)
每周贴士 #175: C++14和C++17里对字面值常量的改变
- 最初发布于:2021-01-30
- 作者:James Dennett
- 更新于:2020-04-06
- 短链接:abseil.io/tips/175
“唯一不变的东西就是变化”——梅莉莎·埃瑟里奇
概述
C++现在有了一些特性,使得数字字面值更易读了。
整数字面值可以被写作二进制了(0b00101010
),正如十进制(42
),十六进制(0x2A
),和八进制(052
)格式这些混沌初分的时候就支持的格式一样。
单引号('
)充当了数位分隔符,并且可以在任何基数的字符串字面值里对数位分组。
浮点数字面值可以写作十六进制了(0x2A0p-4
)。
二进制字面值
形如0b1110'0000
的二进制字面值,在操作比特集合或是处理底层协议的时候,可以比十六进制(次优解)更易读。干这种活的代码在google3里应该很少见,在那里更高层的封装通常是更好的选择。
数位分隔符
C++14允许单引号('
)被用来对数字字面值里的数位进行分组。这些数位分隔符对常量的值没有任何影响:它们唯一的作用是帮助读者。它们可以让人一眼看出数字有多少位,进而确认没有东西被落下。例如,表达十亿的时候,1'000'000'000
比1000000000
更明晰(而且与1e9
不同,它是整数而非浮点数)。
对于每组包含多少位,没有任何限制,甚至在同一字面值里也不要求一致:以0b1'001'0001
来表达数字145是合法的(甚至可能是合理的,如果是表示字节中三个分隔的位域的话)。
十六进制浮点字面值
虽然大部分 十进制 浮点字面值并不是大部分计算机中使用的二进制浮点格式的精确表达,但是 十六进制 浮点字面值确实直接对应浮点数的比特模式,只要比特数管够就行。这样就避免了从字面值转换到浮点格式的舍入误差(当然如果有太多的十六进制数位,截断误差还是会发生)。
十六进制浮点字面值以p
(或P
)为指示,分隔开尾数和幂数——十进制浮点字面值里使用e
(或E
)。例如,0x2Ap12
是表达数值0x2A << 12
的另一种方式,也即0x2A000。幂数总是写为十进制,表示2的指数幂,当然也可以是负的:0x1p-10
就是(精确的)1.0/1024
。
建议
- 二进制字面值应该少写,仅限于关心比特操作的代码。
- 如果数字字面值长到一眼看不出多少位,请考虑使用数位分隔符。
- 当使用数位分隔符的时候,使用习惯的分组大小:
- 对于十进制,如果没有冲突的惯例(例如一些货币),请使用三位一组。
- 对于二进制,推荐每组四个比特(半字节)或者八个比特(字节),除非有语义上更明显的分组方式。
- 对于十六进制,使用每组2,4或8个十六进制数位。