词法元素(一)
C语言词法元素(lexical elements)包括预处理标记(preprocessing-token)和标记(token),其中预处理标记可分为头文件名(header-name)、标识符(identifier)、预处理数(pp-number)、字符常量(character-constant)、字符串字面量(string-literal)、标点符号(punctuator)、不属于上述预处理标记类别的通用字符名(universal character name)、不属于上述预处理标记类别的非空格字符(non-white-space character)等8个类别;标记可分为关键词(keyword)、标识符(identifier)、常量(constant)、字符串字面量(string-literal)、标点符号(punctuator)等5个类别,其相互关系如下图所示:
预处理标记(preprocessing-token)是C程序编译步骤3至步骤6中最小的词汇元素。标记(token)是C程序编译步骤7、步骤8中最小的词汇元素。转换成标记的每个预处理标记应具有关键词、标识符、常量、字符串字面量或者标点符号的词法形式。单个通用字符名应与其它预处理标记类别之一相匹配。
在编译步骤4会使用一种附加类别-位置标识(placemarkers),但位置标识不会在源文件中出现。如果'或者"字符匹配预处理标记的最后一个类别,其行为是未定义的。
预处理标记可以使用空格进行分隔;空格由注释或者空格字符(空格字符包括空格符、水平制表符、换行符、垂直制表符、换页符。)组成,或者同时由两者组成。以下两个预处理指令都是合法的。
#define LENGTH/*长度*/10 #define WIDTH 5 /*宽度*/
在编译步骤4的某些情况下,空格不仅仅可以分隔预处理标记,也可以出现在预处理标记中,但仅限于以下情况:
-- 作为头文件名的一部分,例如:#include "my header.h"。
-- 出现在字符常量或者字符串字面量的引号之间,例如:' '、"Welcome to China"。
将输入流解析成预处理标记时,预处理标记应为构成预处理标记的最长字符序列,例如:
A+++++B
将解析成A ++ ++ + B,而不是A ++ + ++ B;尽管前者是无效的C程序代码,而后者是有效的C程序代码。
上述规则有个例外:头文件名预处理标记仅在#include和#embed预处理指令、__has_include和__has_embed表达式以及#pragma指令中实现定义的位置识别。这种情况下,如果字符序列可以解析为头文件名,也可以解析为字符串字面量,将作为头文件名处理。
一、关键词
ISO/IEC 9899:2024标准提供了54个C语言关键词,具体如下表所示:
| alignas | do | int | struct | while |
| alignof | double | long | switch | _Atomic |
| auto | else | nullptr | thread_local | _BitInt |
| bool | enum | register | true | _Complex |
| break | extern | restrict | typedef | _Decimal128 |
| case | false | return | typeof | _Decimal32 |
| char | float | short | typeof_unqual | _Decimal64 |
| const | for | signed | union | _Generic |
| constexpr | goto | sizeof | unsigned | _Imaginary |
| continue | if | static | void | _Noreturn |
| default | inline | static_assert | volatile |
上述标记区分大小写,保留用作C语言关键词,但属性标记(attribute token)除外,不得用于其它用途。关键词_Imaginary用于指定虚数类型。
下表提供了一些关键词的替代拼写。
| 关键词 | 替代拼写 |
| alignas | _Alignas |
| alignof | _Alignof |
| bool | _Bool |
| static_assert | _Static_assert |
| thread_local | _Thread_local |
这些替代拼写是ISO/IEC 9899:2018标准中的C语言关键词;根据ISO/IEC 9899:2024标准,这些替代拼写已经过时,不建议用于新代码。