ISO/IEC 9899:2011 条款6.4.4——常量
6.4.4 常量
语法
1、constant:
integer-constant
floating-constant
enumeration-constant
character-constant
约束
2、每个常量应该具有一个类型并且一个常量的值应该在其类型可表示的值的范围内。
语义
3、每个常量具有一个类型,由其形式与值决定,稍后详细介绍。
6.4.4.1 整数常量
语法
1、integer-constant:
decimal-constant integer-suffixopt
octal-constant integer-suffixopt
hexadecimal-constant integer-suffixopt
decimal-constant:
nonzero-digit
decimal-constant digit
octal-constant:
0
octal-constant octal-digit
hexadecimal-constant:
hexadecimal-prefix hexadecimal-digit
hexadecimal-constant hexadecimal-digit
hexadecimal-prefix: 以下之一
0x 0X
nonzero-digit: 以下之一
1 2 3 4 5 6 7 8 9
octal-digit: 以下之一
0 1 2 3 4 5 6 7
hexadecimal-digit: 以下之一
0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
integer-suffix:
unsigned-suffx long-suffixopt
unsigned-suffx long-long-suffixopt
long-suffix unsigned-suffxopt
long-long-suffix unsigned-suffxopt
unsigned-suffx: 以下之一
u U
long-long-suffix: 以下之一
ll LL
描述
2、一个整数常量以一个数字开头,但不具有小数点,也不具有指数部分。它可以具有一个前缀用来指定其基数,与一个后缀来指定其类型。
3、一个十进制常量以一个非零数字开头,并由一串十进制数构成。一个八进制常量由一个前缀0开头,后面可选地跟一串仅由0到7所组成的数字。一个十六进制常量由前缀0x或0X构成,后面跟一串十进制数以及字母a(或A)到f(或F),分别表示10到15的值。
语义
4、一个十进制常量的值以基为10进行计算;一个八进制常量的值以基为8进行计算;一个十六进制常量以基为16进行计算。词法上第一个数字是最高有效位[译者注:即最左边的数字]。
5、一个整数常量的类型是相应列表中其值所能被表示的第一个。
6、如果一个整数常量不能用其列表中任一类型来表示,那么它可能具有一个扩展整数类型,如果该扩展整数类型可以表示其值。如果常量的列表中所有类型都是带符号的,那么扩展整数类型应该是带符号的。如果常量的列表中所有类型都是无符号的,那么扩展整数类型也应该是无符号的。如果列表同时包含了带符号与无符号类型,那么扩展整数类型可以具有带符号或无符号。如果一个整数常量不能用其列表中的任一类型来表示,并且也没有扩展整数类型,那么该整数常量不具有类型。
6.4.4.2 浮点常量
语法
1、float-constant:
decimal_floating-constant
hexadecimal-floating-constant
decimal-floating-constant:
fractional_constant exponent-partopt float-suffixopt
digit-sequence exponent-part float-suffixopt
hexadecimal-floating-constant:
hexadecimal-prefix hexadecimal-fractional-constant binary-exponent-part float-suffixopt
hexadecimal-prefix hexadecimal-digit-sequence binary-exponent-part float-suffixopt
fractional-constant:
digit-sequenceopt . digit-sequence
digit-sequence .
exponent-part:
e signopt digit-sequence
E signopt digit-sequence
sign: 以下之一
+ -
digit-sequence:
digit
digit-sequence digit
hexadecimal-fractional-constant:
hexadecimal-digit-sequenceopt . hexadecimal-digit-sequence
hexadecimal-digit-sequence .
binary-exponent-part: p signopt digit-sequence
P signopt digit-sequence
hexadecimal-digit-sequence:
hexadecimal-digit
hexadecimal-digit-sequence hexadecimal-digit
float-suffix: 以下之一
f l F L
描述
2、一个浮点常量具有一个尾数部分,它可以跟在一个指数部分后面,并且也可以有一个后缀来指定其类型。尾数部分的成员可包括一个表示整数部分的数字序列,后面跟小数点(.),后面再跟表示小数部分的数字序列。指数部分的分量为一个e,E,p或P,后面跟由一个可选的带符号数字序列所组成的一个指数。整数部分或小数部分均可缺省;对于十进制浮点常量,小数点或指数部分必须存在其中之一。
语义
3、尾数部分被解释为一个(十进制或十六进制的)有理数;指数部分中的数字序列被解释为一个十进制整数。对于十进制浮点常量,指数指明了10的幂,尾数部分作为它的被乘数。对于十六进制浮点常量,指数指明了2的幂,尾数部分作为它的被乘数。对于十进制浮点常量,以及对于十六进制浮点常量,当FLT_RADIX不为2的幂时,结果要么取最接近可表示的值,要么大于或小于毗邻最近可表示值,如何选择由实现自定义的方式进行。对于十六进制浮点常量,当FLT_RADIX是一个2的幂时,结果被正确地舍入。
4、一个没有后缀的浮点常量具有类型double。如果后缀字母为f或F,那么它具有类型float。如果后缀字母为l或L,那么它具有类型long double。
5、浮点常量被转换为内部格式,就好比在翻译时。一个浮点常量的转换在执行时不应该引发一个异常情况或一个浮点异常。所有相同源形式的浮点常量[注:1.23,1.230,123e-2,123e-02,以及1.23L都是不同的源形式,从而不需要转换为相同的内部格式与值。]应该转换为相同的内部格式,并具有相同的值。
推荐实践
6、如果一个十进制常量不能完全用其计算格式来表示,那么实现应该产生一个诊断消息;实现然后应该将程序的翻译继续执行下去。
7、浮点常量的编译时转换应该通过库函数来匹配字符串的执行时转换,诸如strtod,给定适用于两者转换、相同的结果格式以及默认执行时舍入的匹配输入。[注:用于库函数的规格说明建议比起对于浮点常量的要求更精确的转换。]
6.4.4.3 枚举常量
语法
1、enumeration-constant:
identifier
语义
2、声明为一个枚举常量的一个标识符具有类型int。
6.4.4.4 字符常量
语法
1、character-constant:
' c-char-sequence '
L' c-char-sequence '
u' c-char-sequence '
U' c-char-sequence '
c-char-sequence:
c-char
c-char-sequence c-char
c-char:
源字符集的任一成员,除了单引号 ' ,倒斜杠 \ ,或换行字符
escape-sequence
escape-sequence:
simple-escape-sequence
octal-escape-sequence
hexadecimal-escape-sequence
universal-escape-name
simple-escape-sequence: 以下之一
\' \" \? \\ \a \b \f \n \r \t \v
octal-escape-sequence:
\ octal-digit
\ octal-digit octal-digit
\ octal-digit octal-digit octal-digit
\ octal-digit octal-digit octal-digit octal-digit
hexadecimal-escape-sequence:
\x hexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit
描述
2、一个整数常量是被一对单引号封闭住的一个或多个多字节字符序列,比如'x'。一个宽字符常量也同样如此,除了带有前缀字母L,u或U。序列的元素是源字符集的任一成员,有一些例外稍后会详细描述;它们以实现定义的形式映射到执行字符集的成员。
3、单引号 ' ,双引号 " ,问好 ? ,倒斜杠 \ ,以及任意的整数值根据以下转义序列表来表示:
单引号 ' \'
双引号 " \"
问号 ? \?
倒斜杠 \ \\
八进制字符 \octal digits
十六进制字符 \x hexadecimal digits
4、双引号 " 与问好 ? 亦或可以用它们自身来表示,亦或可以分别用转义符 \" 和 \? 来表示,但是单引号 ' 与倒斜杠 \ 应该分别用转义符 \' 和 \\ 来表示。
5、在一个八进制转义序列中,跟在倒斜杠之后的八进制数字为一个整型字符常量被取为构造一单个字符的一部分,或为一个宽字符常量被取为构造一单个宽字符的一部分。如此所形成的八进制整数的数值指定了所期望的字符的值或宽字符的值。
6、在一个十六进制转义序列中,跟在倒斜杠之后的十六进制数字一记字母x被取为为一个整型字符常量构造一单个字符的一部分,或为一个宽字符常量构造一单个宽字符的一部分。如此形成的十六进制整数的数值指定了所期望的宽字符的字符。
7、每个八进制或十六进制转义序列是可以组成转义序列的最长序列。
8、此外,不在基本字符集中的字符是可以通过通用字符名来表示的,并且某些非可显字符可以用转义序列来表示,通过倒斜杠后面跟一个小写字母:\a,\b,\f,\n,\r,\t,以及\v。[注:这些字符的语义在5.2.2中被讨论。如果任何其它字符后面跟在一个倒斜杠后面,那么结果不是一个标记,并且需要一个诊断。见“未来的语言方向”(6.11.4)。]
约束
9、一个八进制或十六进制转义序列的值应该在相应类型的可表示值的范围内:
前缀 相应类型
无 unsigned char
L 相应于wchar_t的无符号类型
u char16_t
U char32_t
语义
10、一个整型字符常量具有类型int。一个包含射到一单字节执行字符的一单个字符的整型字符常量的值是被解释为一个整数的被映射字符所表示的数值。含有多个字符的一个整型字符常量(比如'ab')的值,或是包含一个字符或转义序列的整型字符常量的值——它们不映射到一单字节执行字符——,是由实现定义的。如果一个整型字符常量包含一单个字符或转义序列,那么其值的结果为,当带有类型char的一个对象,其值为单个字符或转义序列而被转换为类型int。
11、带有前缀字母L的一个宽字符常量具有类型wchar_t,定义在<stddef.h>头文件中的一个整数类型;带有前缀字母u或U的一个宽字符常量分别具有类型char16_t或char32_t,定义在<uchar.h>头文件中的无符号整数类型。包含一单个多字节字符(该多字节字符映射到扩展执行字符集的一单个成员)的一个宽字符常量的值是相应于那个多字节字符的宽字符,通过mbtowc、mbrtoc16或mbrtoc32函数来定义,根据其实际类型来定,带有实现定义的当前本地语言。包含多个多字节字符或一单个多字节字符(映射到扩展执行字符集的多个成员)的一个宽字符常量值,或是包含一不在扩展执行字符集中表示的多字节字符或转义序列的一个宽字符常量,是由实现定义的。
12、例1 '\0' 的构造通常用于表示空字符。
13、例2 考虑对整数以及具有char类型的八位对象使用2的取反表示。在某个实现中,如果类型char具有与signed char相同范围的值,那么整型字符常量 '\xFF' 具有值-1;如果类型char具有与unsigned char相同范围的值,那么字符常量 '\xFF' 具有值+255。
14、例3 即使八比特被用于具有char类型的对象,构造 '\x123' 指定了仅包含一单个字符的一个整数字符常量,由于一个十六进制转义序列仅被一个非十六进制字符终止。为了指定一个包含两个字符的整型字符常量,它们的值分别为'\x12'和'3',构造 '\0223' 可以被使用,由于一个八进制转义序列在三个八进制数字之后被终止。(这个双字符整型字符常量是由实现定义的。)
15、例4 即使有12或更多比特用于具有类型wchar_t的对象,L'\1234'指定了实现定义的值,该值通过0123的值与'4'的值的组合得到。