6.10.1 一般规定
语法
形式化语法
bnf
preprocessing-file:
groupopt
group:
group-part
group group-part
group-part:
if-section
control-line
text-line
# non-directive
if-section:
if-group elif-groupsopt else-groupopt endif-line
if-group:
# if constant-expression new-line groupopt
# ifdef identifier new-line groupopt
# ifndef identifier new-line groupopt
elif-groups:
elif-group
elif-groups elif-group
elif-group:
# elif constant-expression new-line groupopt
# elifdef identifier new-line groupopt
# elifndef identifier new-line groupopt
else-group:
# else new-line groupopt
endif-line:
# endif new-line
control-line:
# include pp-tokens new-line
# embed pp-tokens new-line
# define identifier replacement-list new-line
# define identifier lparen identifier-listopt ) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list , ... ) replacement-list new-line
# undef identifier new-line
# line pp-tokens new-line
# error pp-tokensopt new-line
# warning pp-tokensopt new-line
# pragma pp-tokensopt new-line
# new-line
text-line:
pp-tokensopt new-line
non-directive:
pp-tokens new-line
lparen:
a ( character not immediately preceded by white space
replacement-list:
pp-tokensopt
pp-tokens:
preprocessing-token
pp-tokens preprocessing-token
new-line:
the new-line character
identifier-list:
identifier
identifier-list , identifier
pp-parameter:
pp-parameter-name pp-parameter-clauseopt
pp-parameter-name:
pp-standard-parameter
pp-prefixed-parameter
pp-standard-parameter:
identifier
pp-prefixed-parameter:
identifier :: identifier
pp-parameter-clause:
( pp-balanced-token-sequenceopt )
pp-balanced-token-sequence:
pp-balanced-token
pp-balanced-token-sequence pp-balanced-token
pp-balanced-token:
( pp-balanced-token-sequenceopt )
[ pp-balanced-token-sequenceopt ]
{ pp-balanced-token-sequenceopt }
any pp-token other than a parenthesis, a bracket, or a brace
embed-parameter-sequence:
pp-parameter
embed-parameter-sequence pp-parameter1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
说明
- 预处理指令由一串预处理记号组成,并且必须满足以下条件:
- 该序列的第一个记号必须是
#预处理记号;在翻译阶段4开始时,它要么是源文件中的第一个字符(其前面可以有不含换行字符的空白),要么前面紧邻含有至少一个换行字符的空白。 - 该序列的最后一个记号,是紧随第一个记号之后出现的第一个换行字符。
- 即使这个换行字符出现在本来会被解释为函数式宏调用的地方,它也仍然会结束该预处理指令。
- 文本行不得以
#预处理记号开头。 - 非指令行不得以前述语法中出现的任何指令名开头。
- 有些预处理指令通过预处理器参数传递附加信息。
- 预处理器参数
pp-parameter,要么是预处理器前缀参数,也就是pp-prefixed-parameter,用于实现定义的预处理器参数;要么是预处理器标准参数,也就是pp-standard-parameter,用于本标准规定的参数。 - 对于本标准以标识符
pp_param规定的预处理器标准参数,写成__pp_param__形式的标识符在用作预处理器参数时,除拼写不同外,其行为必须完全相同。
示例
下面两个二进制资源包含指令中的预处理器参数等价:
c
#embed "boop.h" limit(5)
#embed "boop.h" __limit__(5)1
2
2