前言
一个形如20的值称之为字面值常量(literal),这样的值一望而知。每个字面值常量对应一种数据类型,由其形式和值决定。
0x1 整型字面值
整型字面值可以写成十进制数、八进制数、或者十六进制数的形式。例如,我们可以用以下任意一种形式来表示数值20:
int decimal_literals = 20; //十进制
int octal_literals = 024; //八进制
int hexadecimal_literals = 0x14; //十六进制
默认情况下,十进制字面值的类型是int
、long
和long long
中能容纳其数值的最小者。而八进制和十六进制字面值的类型是能容纳其数值的int
、unsigned int
、long
、unsigned long
、long long
和unsigned long long
中的尺寸最小者。若一个字面值连与之关联的最大的数据类型都放不下,将产生错误。
可以通过在常量后添加后缀来声明字面值常量的类型,添加后缀u或U表示为unsigned
,添加后缀l或者L表示为long
类型,添加后缀ll或者LL表示为long long
类型,可以通过组合ul将常量声明为unsigned long
型。例如:
int unsigned_int = 20u; //无符号整型
int signed_long = 20l; //带符号长整型
int signed_long_long = 20ll; //带符号长长整型
将上述两段代码用clang生成语法树如下:
0x2 浮点数字面值
默认情况下,浮点数字面值是一个double
类型,表现为一个小数和科学计数法表示的指数,其中指数部分用E或e标识。可以通过在常量后添加后缀来声明浮点数字面值常量的类型,添加后缀f或F表示为float
,添加后缀l或者L表示为long double
类型。代码示例:
float v1 = 3.14; //3.14是double类型
float v2 = 3.14f; //3.14是float类型
long double v3 = 3.14l; //3.14是long double类型
clang生成语法树如下:
0x3 字符和字符串字面值
由单引号括起来的一个字符称为char型字面值,双引号括起来的零个或多个字符则称为字符串型字面值。字符串字面值的类型实际上是由常量字符构成的数组,其类型为const char []
,在ELF文件中存放于.rodata段。 字符字面值或者字符串字面值通过添加前缀L表示为宽字符wcahr_t
,通过添加前缀u和U可以分别表示为Unicode16字符char16_t
和Unicode32字符char32_t
。特殊的,字符串字面值添加前缀u8可以表示为UTF-8字符串字面值。代码示例:
char c1 = 'A'; //char型常量
wchar_t c2 = L'A'; //宽字符型常量
char16_t c3 = u'A'; //Unicode16字符型常量
char32_t c4 = U'A'; //Unicode32字符型常量
char *s1 = "AAAAA"; //const char [6]类型的常量数组
const char s2[] = u8"AAAAA"; //utf-8字符串字面值常量
clang生成语法树如下:
0x4 转义序列
有两类字符程序员不可以直接使用:一类是不可打印字符,如退格回车等控制字符;另一类是 C++ 中有特殊含义的字符(单引号 '
、双引号 "
、问号 ?
、反斜杠 \
)。在这些情况下需要用到转义序列,转移序列均以反斜杠作为开始。C++ 中规定的转义序列包括有:
- 换行符
\n
- 纵向制表符
\v
- 反斜杠
\\
- 回车符
\r
- 横向制表符
\t
- 退格符
\b
- 问号
\?
- 进纸符
\f
- 报警符
\a
- 双引号
\"
- 单引号
\'
0x5 布尔字面值和指针字面值
true和false是布尔类型的字面值
nullptr是指针字面值
参考资料: 《C++ Prime》、clang官方文档