字面量表达式
语法
LiteralExpression :
CHAR_LITERAL
| STRING_LITERAL
| RAW_STRING_LITERAL
| BYTE_LITERAL
| BYTE_STRING_LITERAL
| RAW_BYTE_STRING_LITERAL
| C_STRING_LITERAL
| RAW_C_STRING_LITERAL
| INTEGER_LITERAL
| FLOAT_LITERAL
|true
|false
字面量表达式是由单个词法单元(Token)组成的表达式,而不是由一系列词法单元组成。它直接表示其求值结果,而不是通过名称或其他求值规则来引用它。
字面量是常量表达式的一种形式,因此(主要)在编译时求值。
前面描述的每个词法字面量形式都可以构成一个字面量表达式,关键字 true
和 false
也可以。
#![allow(unused)] fn main() { "hello"; // string type '5'; // character type 5; // integer type }
在下面的描述中,词法单元的*字符串表示形式*是指输入中与*词法分析器*语法片段中词法单元的产生式相匹配的字符序列。
**注意**:此字符串表示形式永远不会包含字符
U+000D
(CR) 后紧跟U+000A
(LF):这对字符会事先转换为单个U+000A
(LF)。
转义
下面对文本字面量表达式的描述使用了多种形式的*转义*。
每种形式的转义都具有以下特征
- 一个*转义序列*:一个字符序列,始终以
U+005C
(\
) 开头 - 一个*转义值*:单个字符或空字符序列
在下面对转义的定义中
- *八进制数字*是指范围 [
0
-7
] 中的任何字符。 - *十六进制数字*是指范围 [
0
-9
]、[a
-f
] 或 [A
-F
] 中的任何字符。
简单转义
下表第一列中出现的每个字符序列都是一个转义序列。
在每种情况下,转义值都是第二列对应条目中给出的字符。
转义序列 | 转义值 |
---|---|
\0 | U+0000 (NUL) |
\t | U+0009 (HT) |
\n | U+000A (LF) |
\r | U+000D (CR) |
\" | U+0022 (引号) |
\' | U+0027 (撇号) |
\\ | U+005C (反斜杠) |
8 位转义
转义序列由 \x
后跟两位十六进制数字组成。
转义后的值是其 Unicode 标量值 等于将转义序列中的最后两个字符解释为十六进制整数的结果的字符,就像使用基数为 16 的 u8::from_str_radix
一样。
注意:因此,转义后的值的 Unicode 标量值 在
u8
的范围内。
7 位转义
转义序列由 \x
后跟一个八进制数字和一个十六进制数字组成。
转义后的值是其 Unicode 标量值 等于将转义序列中的最后两个字符解释为十六进制整数的结果的字符,就像使用基数为 16 的 u8::from_str_radix
一样。
Unicode 转义
转义序列由 \u{
后跟一系列字符(每个字符都是十六进制数字或 _
)以及 }
组成。
转义后的值是其 Unicode 标量值 等于将转义序列中包含的十六进制数字解释为十六进制整数的结果的字符,就像使用基数为 16 的 u32::from_str_radix
一样。
注意:CHAR_LITERAL 或 STRING_LITERAL 标记的允许形式确保存在这样的字符。
字符串续行转义
转义序列由 \
后跟 U+000A
(LF) 以及在下一个非空白字符之前的任何后续空白字符组成。为此,空白字符为 U+0009
(HT)、U+000A
(LF)、U+000D
(CR) 和 U+0020
(SPACE)。
转义后的值是一个空字符序列。
注意:这种形式的转义的效果是字符串续行会跳过后续的空白,包括额外的换行符。因此,
a
、b
和c
相等#![allow(unused)] fn main() { let a = "foobar"; let b = "foo\ bar"; let c = "foo\ bar"; assert_eq!(a, b); assert_eq!(b, c); }
跳过额外的换行符(如示例 c 所示)可能会造成混淆和意外。此行为将来可能会调整。在做出决定之前,建议避免依赖于使用行继续符跳过多行换行符。有关更多信息,请参阅 此问题。
字符字面量表达式
字符字面量表达式由单个 CHAR_LITERAL 标记组成。
表达式的类型是原始 char
类型。
标记不能有后缀。
标记的字面量内容是在标记的字符串表示形式中第一个 U+0027
('
) 之后和最后一个 U+0027
('
) 之前的字符序列。
字面量表达式的表示字符是从字面量内容派生的,如下所示
-
如果字面量内容是以下转义序列形式之一,则表示的字符是转义序列的转义值
-
否则,表示的字符是构成字面量内容的单个字符。
表达式的值是与表示字符的 Unicode 标量值 对应的 char
。
注意:CHAR_LITERAL 标记的允许形式确保这些规则始终生成单个字符。
字符字面量表达式示例
#![allow(unused)] fn main() { 'R'; // R '\''; // ' '\x52'; // R '\u{00E6}'; // LATIN SMALL LETTER AE (U+00E6) }
字符串字面量表达式
字符串字面量表达式由单个 STRING_LITERAL 或 RAW_STRING_LITERAL 标记组成。
表达式的类型是对原始 str
类型的共享引用(具有 static
生命周期)。也就是说,类型是 &'static str
。
标记不能有后缀。
标记的字面量内容是在标记的字符串表示形式中第一个 U+0022
("
) 之后和最后一个 U+0022
("
) 之前的字符序列。
字面量表达式的表示字符串是从字面量内容派生的字符序列,如下所示
-
如果标记是 STRING_LITERAL,则字面量内容中出现的以下任何形式的每个转义序列都将替换为转义序列的转义值。
这些替换按从左到右的顺序进行。例如,标记
"\\x41"
将转换为字符\
x
4
1
。 -
如果标记是 RAW_STRING_LITERAL,则表示的字符串与字面量内容相同。
表达式的值是对包含表示字符串的 UTF-8 编码的静态分配的 str
的引用。
字符串字面量表达式示例
#![allow(unused)] fn main() { "foo"; r"foo"; // foo "\"foo\""; r#""foo""#; // "foo" "foo #\"# bar"; r##"foo #"# bar"##; // foo #"# bar "\x52"; "R"; r"R"; // R "\\x52"; r"\x52"; // \x52 }
字节字面量表达式
字节字面量表达式由单个 BYTE_LITERAL 标记组成。
表达式的类型是原始 u8
类型。
标记不能有后缀。
标记的字面量内容是在标记的字符串表示形式中第一个 U+0027
('
) 之后和最后一个 U+0027
('
) 之前的字符序列。
字面量表达式的表示字符是从字面量内容派生的,如下所示
表达式的值是表示字符的 Unicode 标量值。
注意:BYTE_LITERAL 标记的允许形式确保这些规则始终生成单个字符,其 Unicode 标量值在
u8
的范围内。
字节字面量表达式示例
#![allow(unused)] fn main() { b'R'; // 82 b'\''; // 39 b'\x52'; // 82 b'\xA0'; // 160 }
字节字符串字面量表达式
字节字符串字面量表达式由单个 BYTE_STRING_LITERAL 或 RAW_BYTE_STRING_LITERAL 标记组成。
表达式的类型是对数组的共享引用(具有 static
生命周期),其元素类型为 u8
。也就是说,类型是 &'static [u8; N]
,其中 N
是下面描述的表示字符串中的字节数。
标记不能有后缀。
标记的字面量内容是在标记的字符串表示形式中第一个 U+0022
("
) 之后和最后一个 U+0022
("
) 之前的字符序列。
字面量表达式的表示字符串是从字面量内容派生的字符序列,如下所示
-
如果标记是 BYTE_STRING_LITERAL,则字面量内容中出现的以下任何形式的每个转义序列都将替换为转义序列的转义值。
这些替换按从左到右的顺序进行。例如,标记
b"\\x41"
将转换为字符\
x
4
1
。 -
如果标记是 RAW_BYTE_STRING_LITERAL,则表示的字符串与字面量内容相同。
表达式的值是对静态分配的数组的引用,该数组包含表示字符串中字符的 Unicode 标量值,顺序相同。
注意:BYTE_STRING_LITERAL 和 RAW_BYTE_STRING_LITERAL 标记的允许形式确保这些规则始终生成
u8
范围内的数组元素值。
字节字符串字面量表达式示例
#![allow(unused)] fn main() { b"foo"; br"foo"; // foo b"\"foo\""; br#""foo""#; // "foo" b"foo #\"# bar"; br##"foo #"# bar"##; // foo #"# bar b"\x52"; b"R"; br"R"; // R b"\\x52"; br"\x52"; // \x52 }
C 字符串字面量表达式
C 字符串字面量表达式由单个 C_STRING_LITERAL 或 RAW_C_STRING_LITERAL 标记组成。
表达式的类型是对标准库 CStr 类型的共享引用(具有 static
生命周期)。也就是说,类型是 &'static core::ffi::CStr
。
标记不能有后缀。
标记的字面量内容是在标记的字符串表示形式中第一个 "
之后和最后一个 "
之前的字符序列。
字面量表达式的表示字节是从字面量内容派生的字节序列,如下所示
-
如果标记是 C_STRING_LITERAL,则字面量内容将被视为一系列项目,每个项目要么是除
\
之外的单个 Unicode 字符,要么是 转义。项目序列将按如下方式转换为字节序列- 每个单个 Unicode 字符都贡献其 UTF-8 表示形式。
- 每个 简单转义 都贡献其转义值的 Unicode 标量值。
- 每个 8 位转义 都贡献一个包含其转义值的 Unicode 标量值 的字节。
- 每个 unicode 转义 都贡献其转义值的 UTF-8 表示形式。
- 每个 字符串续行转义 都不贡献任何字节。
-
如果标记是 RAW_C_STRING_LITERAL,则表示的字节是字面量内容的 UTF-8 编码。
注意:C_STRING_LITERAL 和 RAW_C_STRING_LITERAL 标记的允许形式确保表示的字节永远不包含空字节。
表达式的值是对静态分配的 CStr 的引用,其字节数组包含表示的字节,后跟一个空字节。
C 字符串字面量表达式示例
#![allow(unused)] fn main() { c"foo"; cr"foo"; // foo c"\"foo\""; cr#""foo""#; // "foo" c"foo #\"# bar"; cr##"foo #"# bar"##; // foo #"# bar c"\x52"; c"R"; cr"R"; // R c"\\x52"; cr"\x52"; // \x52 c"æ"; // LATIN SMALL LETTER AE (U+00E6) c"\u{00E6}"; // LATIN SMALL LETTER AE (U+00E6) c"\xC3\xA6"; // LATIN SMALL LETTER AE (U+00E6) c"\xE6".to_bytes(); // [230] c"\u{00E6}".to_bytes(); // [195, 166] }
整数字面量表达式
整数字面量表达式由单个 INTEGER_LITERAL 标记组成。
如果标记有 后缀,则后缀必须是 原始整数类型 之一的名称:u8
、i8
、u16
、i16
、u32
、i32
、u64
、i64
、u128
、i128
、usize
或 isize
,并且表达式具有该类型。
如果标记没有后缀,则表达式的类型由类型推断确定
-
如果可以从周围的程序上下文中唯一地确定整数类型,则表达式具有该类型。
-
如果程序上下文对类型施加的约束不足,则默认为有符号 32 位整数
i32
。 -
如果程序上下文对类型施加的约束过多,则被视为静态类型错误。
整数字面量表达式示例
#![allow(unused)] fn main() { 123; // type i32 123i32; // type i32 123u32; // type u32 123_u32; // type u32 let a: u64 = 123; // type u64 0xff; // type i32 0xff_u8; // type u8 0o70; // type i32 0o70_i16; // type i16 0b1111_1111_1001_0000; // type i32 0b1111_1111_1001_0000i64; // type i64 0usize; // type usize }
表达式的值按如下方式从标记的字符串表示形式确定
-
通过检查字符串的前两个字符来选择整数基数,如下所示
0b
表示基数 20o
表示基数 80x
表示基数 16- 否则,基数为 10。
-
如果基数不是 10,则从字符串中删除前两个字符。
-
从字符串中删除任何后缀。
-
从字符串中删除任何下划线。
-
字符串将转换为
u128
值,就像使用所选基数的u128::from_str_radix
一样。如果该值不适合u128
,则这是一个编译器错误。 -
u128
值将通过 数字强制转换 转换为表达式的类型。
注意:如果字面量的值不适合表达式的类型,则最终的强制转换将截断该值。
rustc
包含一个名为overflowing_literals
的 lint 检查,默认为deny
,它会拒绝发生这种情况的表达式。
注意:例如,
-1i8
是将 取反运算符 应用于字面量表达式1i8
的结果,而不是单个整数字面量表达式。有关表示带符号类型的最小值的说明,请参阅溢出。
浮点数字面量表达式
浮点数字面量表达式有以下两种形式之一
- 单个 FLOAT_LITERAL 标记
- 单个带有后缀且没有基数指示符的 INTEGER_LITERAL 标记
如果标记具有 后缀,则后缀必须是 基本浮点类型 之一的名称:f32
或 f64
,并且表达式具有该类型。
如果标记没有后缀,则表达式的类型由类型推断确定
-
如果可以从周围的程序上下文中唯一地确定浮点类型,则表达式具有该类型。
-
如果程序上下文对类型施加的约束不足,则默认为
f64
。 -
如果程序上下文对类型施加的约束过多,则被视为静态类型错误。
浮点数字面量表达式的示例
#![allow(unused)] fn main() { 123.0f64; // type f64 0.1f64; // type f64 0.1f32; // type f32 12E+99_f64; // type f64 5f32; // type f32 let x: f64 = 2.; // type f64 }
表达式的值按如下方式从标记的字符串表示形式确定
-
从字符串中删除任何后缀。
-
从字符串中删除任何下划线。
-
字符串将转换为表达式的类型,就像通过
f32::from_str
或f64::from_str
进行转换一样。
注意:例如,
-1.0
是将 取反运算符 应用于字面量表达式1.0
的结果,而不是单个浮点数字面量表达式。
注意:
inf
和NaN
不是字面量标记。可以使用f32::INFINITY
、f64::INFINITY
、f32::NAN
和f64::NAN
常量来代替字面量表达式。在rustc
中,大到足以被评估为无穷大的字面量将触发overflowing_literals
lint 检查。
布尔字面量表达式
布尔字面量表达式由关键字 true
或 false
之一组成。
表达式的类型是基本 布尔类型,其值为
- 如果关键字是
true
,则为 true - 如果关键字是
false
,则为 false