关键字
关键字(Keyword)是 C 语言保留的标识符,具有特殊语法含义,不能用作变量名、函数名或其他标识符。C99 共定义了 37 个关键字,掌握它们是阅读任何 C 代码的基础。
C99 关键字列表
| 关键字 | 用途 |
|---|---|
auto | 自动存储期(默认,极少显式使用) |
break | 跳出循环或 switch |
case | switch 分支标签 |
char | 字符类型 |
const | 只读限定 |
continue | 跳过本次循环剩余部分 |
default | switch 默认分支 |
do | do-while 循环 |
double | 双精度浮点 |
else | if 的否定分支 |
enum | 枚举类型 |
extern | 外部链接声明 |
float | 单精度浮点 |
for | for 循环 |
goto | 无条件跳转 |
if | 条件判断 |
inline | 内联函数(C99 新增) |
int | 整数类型 |
long | 长整型修饰符 |
register | 建议寄存器存储 |
restrict | 指针别名限定(C99 新增) |
return | 函数返回 |
short | 短整型修饰符 |
signed | 有符号修饰符 |
sizeof | 获取类型/对象大小 |
static | 静态存储期或内部链接 |
struct | 结构体类型 |
switch | 多分支选择 |
typedef | 类型别名 |
union | 联合体类型 |
unsigned | 无符号修饰符 |
void | 无类型/空参数列表 |
volatile | 易变限定(禁止优化) |
while | while 循环 |
_Bool | 布尔类型(C99 新增) |
_Complex | 复数类型(C99 新增) |
_Imaginary | 虚数类型(C99 新增) |
关键字不能作为标识符
以下代码全部非法:
int int; /* 错误:int 是关键字 */
int return; /* 错误:return 是关键字 */
void void(void); /* 错误:void 是关键字 */
/* 以下看似合法,实际也非法 */
int INT; /* 合法:C 区分大小写,INT 不是关键字 */
int Int; /* 合法:Int 不是关键字 */
C 语言区分大小写,所以 Int、INT、iNt 都不是关键字,可以作为标识符。但为了避免混淆,不建议使用与关键字仅大小写不同的名字。
关键字的分类
数据类型相关:char、short、int、long、float、double、signed、unsigned、void、_Bool、_Complex、_Imaginary
unsigned long int x; /* 类型修饰符组合 */
控制流相关:if、else、switch、case、default、while、do、for、break、continue、goto、return
if (x > 0) return x;
else return -x;
存储类相关:auto、static、extern、register
static int count = 0; /* 静态存储期 */
类型构造相关:struct、union、enum、typedef
typedef struct Node {
int data;
struct Node *next;
} Node;
其他:const、volatile、inline、restrict、sizeof
const int max = 100; /* 只读变量 */
扩展关键字
某些编译器提供扩展关键字(如 GCC 的 __attribute__、MSVC 的 __declspec),这些不是标准 C 的一部分,但广泛支持。使用扩展关键字会降低代码的可移植性,应谨慎使用或在条件编译中隔离。
/* GCC 扩展:指定函数属性 */
__attribute__((noreturn)) void exit_now(void);
/* 更安全的做法:用宏封装 */
#ifdef __GNUC__
#define NORETURN __attribute__((noreturn))
#else
#define NORETURN
#endif
NORETURN void exit_now(void);
记忆建议
不需要死记硬背所有关键字。随着学习的深入,你会在代码中反复遇到它们。建议重点关注:
- 数据类型关键字(
int、char、float、double、void) - 控制流关键字(
if、else、for、while、return) - 其他关键字在学到对应章节时自然掌握
一个实用的检查方法:如果你不确定某个名字是否是关键字,尝试用它作为变量名编译——如果编译器报错"expected identifier before 'xxx'",那它就是关键字。