整数字面量
允许直接在表达式中使用整数类型的值。
语法
整数字面量形式如下:
1 | 十进制字面量 | 整数后缀 | (可选) | |||
2 | 八进制字面量 | 整数后缀 | (可选) | |||
3 | 十六进制字面量 | 整数后缀 | (可选) | |||
4 | 二进制字面量 | 整数后缀 | (可选) | (自 C++14 起) |
其中:
- 十进制字面量 是一个非零的十进制数字(1, 2, 3, 4, 5, 6, 7, 8, 9),后跟零个或多个十进制数字(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
- 八进制字面量 是数字零(0),后跟零个或多个八进制数字(0, 1, 2, 3, 4, 5, 6, 7)
- 十六进制字面量 是字符序列 0x 或字符序列 0X,后跟一个或多个十六进制数字(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, A, b, B, c, C, d, D, e, E, f, F)
- 二进制字面量 是字符序列
0b
或字符序列0B
,后跟一个或多个二进制数字(0, 1) 整数后缀,如果提供,可能包含以下一项或两项(如果两项都提供,可以按任何顺序出现)
- 无符号后缀(字符
u
或字符U
) 以下之一
- 长整型后缀(字符
l
或字符L
) - 长长整型后缀(字符序列
ll
或字符序列LL
) (自 C++11 起) - size后缀(字符
z
或字符Z
) (自 C++23 起)
- 长整型后缀(字符
- 无符号后缀(字符
'
可以插入数字之间作为分隔符;在确定字面量值时会被忽略。 (自 C++14 起)
整数字面量(与其他任何字面量一样)是主表达式。
解释
- 十进制整数字面量(基数 10)。
- 八进制整数字面量(基数 8)。
- 十六进制整数字面量(基数 16,字母 'a' 到 'f' 代表值(十进制)10 到 15)。
- 二进制整数字面量(基数 2)。整数字面量的第一个数字是最重要的。
示例。以下变量被初始化为相同的值
int d = 42;
int o = 052;
int x = 0x2a;
int X = 0X2A;
int b = 0b101010; // C++14
示例。以下变量也被初始化为相同的值
unsigned long long l1 = 18446744073709550592ull; // C++11
unsigned long long l2 = 18'446'744'073'709'550'592llu; // C++14
unsigned long long l3 = 1844'6744'0737'0955'0592uLL; // C++14
unsigned long long l4 = 184467'440737'0'95505'92LLU; // C++14
字面量的类型
整数字面量的类型是其值可以容纳的第一个类型,该类型列表取决于使用的数字基数和整数后缀
后缀 | 十进制基数 | 二进制、八进制或十六进制基数 |
---|---|---|
(无后缀) |
|
|
u 或 U |
|
|
l 或 L |
|
|
l/L 和 u/U 均有 |
|
|
ll 或 LL |
|
|
ll/LL 和 u/U 均有 |
|
|
z 或 Z |
|
|
z/Z 和 u/U 均有 |
|
|
如果整数字面量的值(不带 size 后缀 (自 C++23 起))过大,无法适应后缀/基数组合所允许的任何类型,并且编译器支持可以表示该字面量值的扩展整数类型(例如 __int128
),则该字面量可以被赋予该扩展整数类型——否则程序将格式错误。
备注
整数字面量中的字母不区分大小写:0xDeAdBeEfU 和 0XdeadBEEFu 表示相同的数字 (一个例外是 长长整型后缀,只能是 ll
或 LL
,绝不能是 lL
或 Ll
) (自 C++11 起)。
没有负整数字面量。像 -1
这样的表达式会应用于字面量所代表的值,这可能涉及隐式类型转换。
在 C(C99 之前)中(但在 C++ 中不是),未加后缀的十进制值如果不适合 long int
,则可以具有 unsigned long int
类型。
在 #if
或 #elif
的控制表达式中使用时,所有有符号整数常量都表现为 std::intmax_t
类型,所有无符号整数常量都表现为 std::uintmax_t
类型 (自 C++11 起).
由于最大吞食,以 e
和 E
结尾的十六进制整数字面量,后面紧跟 +
或 -
运算符时,必须用空格或括号将它们与运算符分隔开
auto x = 0xE+2.0; // error
auto y = 0xa+2.0; // OK
auto z = 0xE +2.0; // OK
auto q = (0xE)+2.0; // OK
否则,会形成一个无效的预处理数字标记,导致后续分析失败。
功能测试宏 | 值 | 标准 | 注释 |
---|---|---|---|
__cpp_binary_literals | 201304L | (C++14) | 二进制字面量 |
__cpp_size_t_suffix | 202011L | (C++23) | std::size_t 及其有符号版本的字面量后缀 |
示例
#include <cstddef>
#include <iostream>
#include <type_traits>
int main()
{
std::cout << 123 << '\n'
<< 0123 << '\n'
<< 0x123 << '\n'
<< 0b10 << '\n'
<< 12345678901234567890ull << '\n'
<< 12345678901234567890u << '\n'; // the type is unsigned long long
// even without a long long suffix
// std::cout << -9223372036854775808 << '\n'; // error: the value
// 9223372036854775808 cannot fit in signed long long, which is the
// biggest type allowed for unsuffixed decimal integer literal
std::cout << -9223372036854775808u << '\n'; // unary minus applied to unsigned
// value subtracts it from 2^64, this gives 9223372036854775808
std::cout << -9223372036854775807 - 1 << '\n'; // correct way to calculate
// the value -9223372036854775808
#if __cpp_size_t_suffix >= 202011L // C++23
static_assert(std::is_same_v<decltype(0UZ), std::size_t>);
static_assert(std::is_same_v<decltype(0Z), std::make_signed_t<std::size_t>>);
#endif
}
123
83
291
2
12345678901234567890
12345678901234567890
9223372036854775808
-9223372036854775808
缺陷报告
以下改变行为的缺陷报告已追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 发布时的行为 | 正确行为 |
---|---|---|---|
CWG 2698 | (C++23) | 带 size 后缀的整数字面量可以有扩展整数类型 | 如果太大,则格式错误 |
参考文献
- C++23 标准 (ISO/IEC 14882:2023)
- 5.13.2 Integer literals [lex.icon]
- C++20 标准 (ISO/IEC 14882:2020)
- 5.13.2 Integer literals [lex.icon]
- C++17 标准 (ISO/IEC 14882:2017)
- 5.13.2 Integer literals [lex.icon]
- C++14 标准 (ISO/IEC 14882:2014)
- 2.14.2 Integer literals [lex.icon]
- C++11 标准 (ISO/IEC 14882:2011)
- 2.14.2 Integer literals [lex.icon]
- C++98 标准 (ISO/IEC 14882:1998)
- 2.13.1 Integer literals [lex.icon]