C编程
关键字表
ANSI(美国国家标准协会)C(C89)/ISO C(C90)
非常旧的编译器可能无法识别一些或所有C89关键字,如 const
、enum
、signed
、void
、volatile
,以及任何后续标准中的关键字。
关键字 |
---|
auto |
break |
case |
char |
const |
continue |
default |
do |
double |
else |
enum |
extern |
float |
for |
goto |
if |
int |
long |
register |
return |
short |
signed |
sizeof |
static |
struct |
switch |
typedef |
union |
unsigned |
void |
volatile |
while |
ISO C(C99)
这些关键字在大多数新编译器中得到支持。
关键字 |
---|
_Bool |
_Complex |
_Imaginary |
inline |
restrict |
ISO C(C11)
这些关键字仅在一些较新的编译器中得到支持。
关键字 |
---|
alignof |
_Alignas |
_Atomic |
_Generic |
_Noreturn |
_Static_assert |
_Thread_local |
虽然不严格来说是关键字,但C99兼容的预处理器/编译器还识别特殊的预处理器操作符 _Pragma
,它作为 #pragma
指令的另一种形式,可以在宏展开时使用。例如,以下代码会导致一些编译器(如 GCC、Clang)发出诊断信息:
#define EMIT_MESSAGE(str) EMIT_PRAGMA(message(str))
#define EMIT_PRAGMA(content) _Pragma(#content)
EMIT_MESSAGE("Hello, world!")
一些编译器使用稍微不同的语法;特别是,MSVC支持 __pragma
代替 _Pragma
。
特定编译器可能还会在非标准兼容模式下,或者通过额外的语法标记(如 __extension__
)将一些其他词汇视为关键字,包括 asm
、cdecl
、far
、fortran
、huge
、interrupt
、near
、pascal
或 typeof
。然而,它们通常允许在标准兼容模式下通过声明来覆盖这些关键字(例如,通过定义一个名为 typeof
的变量),以避免与现有程序不兼容。为了确保编译器能够维护对扩展功能的访问,这些编译器通常会有一组以两个下划线(__
)开头的适当关键字。例如,GCC将 asm
、__asm
和 __asm__
视为相似,但后两个始终保证具有预期的含义,因为它们无法被覆盖。
许多新引入的关键字——特别是那些以下划线和大写字母开头的,如 _Noreturn
或 _Imaginary
——通常是间接使用的。开发人员应优先使用标准头文件,如 <stdbool.h>
或 <stdalign.h>
,这些文件通常使用预处理器来建立该关键字的小写变体(例如,complex
或 noreturn
)。这些头文件的目的是使 C 和 C++ 代码以及针对不同编译器或语言版本的代码能够更清洁地互操作。例如,通过包含 <stdbool.h>
,在C99或C++中可以无差别地使用 bool
、true
和 false
,而不需要在C99中显式使用 _Bool
或在C++中使用 bool
。
另见保留标识符列表 。
运算符表
此表中同一行的运算符具有相同的优先级,评估顺序由结合性(从左到右或从右到左)决定。表格中越接近顶部的运算符优先级越高,优先级较低的运算符位于后续的组别中。
运算符类型 | 描述 | 示例用法 | 结合性 |
---|---|---|---|
后缀运算符 | 左到右 | ||
() |
函数调用运算符 | swap(x, y) |
左到右 |
[] |
数组下标运算符 | arr[i] |
左到右 |
. |
成员访问运算符,适用于结构体/联合体类型的对象或其引用 | obj.member |
左到右 |
-> |
成员访问运算符,适用于指向结构体/联合体对象的指针 | ptr->member |
左到右 |
| 一元运算符 | 右到左 | | !
| 逻辑非运算符 | !eof_reached
| 右到左 | | ~
| 按位非运算符 | ~mask
| 右到左 | | + -
| 一元正负号运算符 | -num
| 右到左 | | ++ --
| 后置自增/自减运算符 | num++
| 右到左 | | ++ --
| 前置自增/自减运算符 | ++num
| 右到左 | | &
| 地址运算符 | &data
| 右到左 | | *
| 间接运算符 | *ptr
| 右到左 | | sizeof
| 表达式的大小运算符 | sizeof 123
| 右到左 | | sizeof()
| 类型的大小运算符 | sizeof(int)
| 右到左 | | (type)
| 类型转换运算符 | (float)i
| 右到左 |
| 乘法运算符 | 左到右 | | * / %
| 乘法、除法和取模运算符 | celsius_diff * 9.0 / 5.0
| 左到右 |
| 加法运算符 | 左到右 | | + -
| 加法和减法运算符 | end - start + 1
| 左到右 |
| 位移运算符 | 左到右 | | <<
| 左移运算符 | bits << shift_len
| 左到右 | | >>
| 右移运算符 | bits >> shift_len
| 左到右 |
| 关系不等运算符 | 左到右 | | < > <= >=
| 小于、大于、小于或等于、大于或等于运算符 | i < num_elements
| 左到右 |
| 关系等于运算符 | 左到右 | | == !=
| 等于、不等于运算符 | choice != 'n'
| 左到右 |
| 按位与运算符 | 左到右 | | &
| 按位与运算符 | bits & clear_mask_complement
| 左到右 |
| 按位异或运算符 | 左到右 | | ^
| 按位异或运算符 | bits ^ invert_mask
| 左到右 |
| 按位或运算符 | 左到右 | | |
| 按位或运算符 | bits | set_mask
| 左到右 |
| 逻辑与运算符 | 左到右 | | &&
| 逻辑与运算符 | arr != 0 && arr->len != 0
| 左到右 |
| 逻辑或运算符 | 左到右 | | ||
| 逻辑或运算符 | arr == 0 || arr->len == 0
| 左到右 |
| 条件运算符 | 右到左 | | ?:
| 条件运算符 | size != 0 ? size : 0
| 右到左 |
| 赋值运算符 | 右到左 | | =
| 赋值运算符 | i = 0
| 右到左 | | += -= *= /=
| 复合赋值运算符 | num /= 10
| 右到左 | | %=
&=
|=
^=
<<=
>>=
| 按位与、按位或、按位异或、按位移赋值运算符 | num /= 10
| 右到左 |
| 逗号运算符 | 左到右 | | ,
| 逗号运算符 | i = 0, j = i + 1, k = 0
| 左到右 |
数据类型表
类型 | 位数 | 备注 | 替代名称 |
---|---|---|---|
ANSI C (C89)/ISO C (C90) 中的基本类型 | |||
char |
≥ 8 | sizeof 返回以字符为单位的大小。这些“C字节”不必是8位字节(尽管通常是);字节数由 limits.h 头文件中的 CHAR_BIT 宏给出。符号性由实现定义。可以使用任何编码的8位或更少(例如 ASCII)来存储字符。整数运算仅对 0 ~ 127 范围内的值可移植。所有位都对 char 的值有贡献,即没有“空洞”或“填充”位。 |
— |
signed char |
与 char 相同 |
字符存储方式与 char 类型相同。可以可移植地存储范围为 -127 ~ 127 的整数。 |
— |
unsigned char |
与 char 相同 |
字符存储方式与 char 类型相同。可以可移植地存储范围为 0 ~ 255 的整数。 |
— |
short |
≥ 16,≥ char 的大小 |
可以可移植地存储范围为 -32767 ~ 32767 的整数。用于减少内存使用(尽管与 int 比较,生成的可执行文件可能更大且可能更慢)。 |
short int , signed short , signed short int |
unsigned short |
与 short 相同 |
可以可移植地存储范围为 0 ~ 65535 的整数。用于减少内存使用(尽管与 int 比较,生成的可执行文件可能更大且可能更慢)。 |
unsigned short int |
int |
≥ 16,≥ short 的大小 |
表示处理器处理的数据的“正常”大小(字长);这是通常使用的整数数据类型。可以可移植地存储范围为 -32767 ~ 32767 的整数。 | signed , signed int |
unsigned int |
与 int 相同 |
可以可移植地存储范围为 0 ~ 65535 的整数。 | unsigned |
long |
≥ 32,≥ int 的大小 |
可以可移植地存储范围为 -2147483647 ~ 2147483647 的整数。 | long int , signed long , signed long int |
unsigned long |
与 long 相同 |
可以可移植地存储范围为 0 ~ 4294967295 的整数。 | unsigned long int |
float |
≥ char 的大小 |
当使用的值变化不大时,用于减少内存使用。浮点格式由实现定义,不一定是 IEEE 单精度格式。unsigned 不能指定。 |
— |
double |
≥ float 的大小 |
表示处理器处理的数据的“正常”大小;这是通常使用的浮点数据类型。浮点格式由实现定义,不一定是 IEEE 双精度格式。unsigned 不能指定。 |
— |
long double |
≥ double 的大小 |
unsigned 不能指定。 |
— |
| ISO C (C99) 中新增的基本类型 | | | | | long long
| ≥ 64,≥ long
的大小 | 可以可移植地存储范围为 -9223372036854775807 ~ 9223372036854775807 的整数。 | long long int
, signed long long
, signed long long int
| | unsigned long long
| 与 long long
相同 | 可以可移植地存储范围为 0 ~ 18446744073709551615 的整数。 | unsigned long long int
| | intmax_t
| 平台支持的最大宽度 | 可以存储范围为 -(1 << n-1) + 1 ~ (1 << n-1) - 1 的整数,其中 n
为 intmax_t
的宽度。用于 C 编程中的“j”长度修饰符,特别是在格式化输出函数(如 printf
)中。 | — | | uintmax_t
| 与 intmax_t
相同 | 可以存储范围为 0 ~ (1 << n) - 1 的整数,其中 n
为 uintmax_t
的宽度。 | — |
| 用户定义类型 | | | | | struct
| ≥ 各成员的大小之和 | 称为聚合类型。 | — | | union
| ≥ 最大成员的大小 | 称为聚合类型。 | — | | enum
| ≥ char
的大小 | 枚举是与整数不同的类型,尽管它们是可以互相转换的。 | — | | typedef
| 与被赋予名称的类型相同 | typedef
的语法与存储类如 static
, register
或 extern
相似。 | — |
| 派生类型 | | | | | type*
(指针) | ≥ char
的大小 | 0 始终表示空指针(无法存放数据的地址),无论空指针的位序列如何表示。指向不同类型的指针可能具有不同的表示方式,这意味着它们的大小也可能不同。因此,指针类型不可相互转换。即使在保证所有数据指针大小相同的实现中,函数指针和数据指针通常也不兼容。对于传递可变参数的函数,传递的参数必须是适当类型,因此即使是 0 也必须在这样的函数调用中强制转换为适当的类型。 | — | | type [integer[8]]
(数组) | ≥ 整数 × type
的大小 | 方括号([]
)在声明中跟随标识符名称。在包含数组初始化的声明中(包括函数参数声明),数组的大小(整数)可以省略。type []
不同于 type*
,只有在某些情况下,二者才可以相互转换。 | — | | type (逗号分隔的类型/声明列表)
(函数) | — | 声明没有任何存储类的函数为 extern
。圆括号(()
)跟随标识符名称,例如:一个 2 参数的函数指针:int (* fptr)(int arg1, int arg2)
。 | — |
字符集
用 C 语言编写的程序可以读取和写入任何字符集,前提是包含或使用了支持这些字符集的库。
然而,C 程序的源代码通常仅限于 ASCII 字符集。
在包含源代码的文件中,行的结束有时根据创建文件的操作系统不同,可能不是换行符,但编译器会将每行的结束处理为单个换行符。
几乎所有的编译器都允许 $
、@
和 `
字符在字符串常量中使用。许多编译器还允许使用字面上的多字节 Unicode 字符,但它们并不具备可移植性。
某些字符必须使用反斜杠转义,以便在字符串或字符常量中表示它们自己。这些字符包括:
\\
:字面反斜杠\"
:字面双引号\'
:字面单引号\n
:换行符\t
:水平制表符\f
:换页符\v
:垂直制表符
此外,某些编译器还允许以下字符:
\r
:回车符\a
:警报(可听的铃声)\b
:退格符\xhh
,其中'h'
为十六进制数字,用于表示任意字节(包括\x00
,零字节)。
\uhhhh
或 \Uhhhhhhhh
,其中 'h'
为十六进制数字,用于可移植地表示 Unicode 字符。
参考
- IBM文档:保留标识符列表
- 非常老旧的编译器可能无法识别一元加号(+)操作符。
- -128 可以存储在二进制补码机器中(即大多数现有机器)。非常老旧的编译器可能无法识别
signed
关键字。 - -32768 可以存储在二进制补码机器中(即大多数现有机器)。非常老旧的编译器可能无法识别
signed
关键字。 - -2147483648 可以存储在二进制补码机器中(即大多数现有机器)。非常老旧的编译器可能无法识别
signed
关键字。 - -9223372036854775808 可以存储在二进制补码机器中(即大多数现有机器)。
声明中的优先级:
[]
、()
(左结合性)— 最高*
(右结合性)— 最低