第一章:关键字和标识符(🔥)
1.1 关键字
1.1.1 概述
- 在 C 语言中,
关键字是由C 语言标准预先规定、具有特殊含义的单词。
点我查看 具体细节
- ① 关键字 = C 语言自己保留使用的单词。
- ② 程序员
不能将关键字当成变量名、函数名以及结构体等标识符去使用。 - ③ C 语言中的关键字是不需要强行记忆,等用到的时候,自然而然就记住了。
- ④ 在
高级记事本软件或IDE(集成开发环境中),关键字非常好区分,因为其具有特殊的颜色。 - ⑤ C 语言中的
关键字定义了语言的语法和结构,并决定了程序的控制流、数据结构等方面的行为。
c
#include <stdio.h>
// int 是关键字
int main() {
printf("Hello World\n");
// return 是关键字
return 0;
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10

1.1.2 C 语言中的关键字
- C 语言中的关键字,如下所示:
点我查看 具体细节
- ① 基本数据类型,如下所示:
| 关键字 | 首次标准 | 含义 / 用途 |
|---|---|---|
void | C89 | 无类型,无返回值 |
char | C89 | 字符 / 小整数类型 |
short | C89 | 短整数类型或修饰 |
int | C89 | 整数类型 |
long | C89 | 长整数类型或修饰 |
signed | C89 | 有符号整数 |
unsigned | C89 | 无符号整数 |
float | C89 | 单精度浮点数 |
double | C89 | 双精度浮点数 |
_Bool | C99 新增 | 布尔类型(旧式名称) |
bool | C23 新增 | 布尔类型 |
_Complex | C99 新增 | 复数类型 |
_Imaginary | C99 新增 | 虚数类型 |
_BitInt | C23 新增 | 指定位宽整数 |
_Decimal32 | C23 新增 | 32 位十进制浮点 |
_Decimal64 | C23 新增 | 64 位十进制浮点 |
_Decimal128 | C23 新增 | 128 位十进制浮点 |
- ② 结构与自定义类型,如下所示:
| 关键字 | 首次标准 | 含义 / 用途 |
|---|---|---|
struct | C89 | 定义结构体 |
union | C89 | 定义联合体 |
enum | C89 | 定义枚举类型 |
typedef | C89 | 为类型定义别名 |
- ③ 条件与分支控制,如下所示:
| 关键字 | 首次标准 | 含义 / 用途 |
|---|---|---|
if | C89 | 条件成立时执行 |
else | C89 | 条件不成立时执行 |
switch | C89 | 多分支选择 |
case | C89 | switch 的具体分支 |
default | C89 | switch 的默认分支 |
- ④ 存储类别与生命周期,如下所示:
| 关键字 | 首次标准 | 含义 / 用途 |
|---|---|---|
auto | C89 | 自动存储期 |
register | C89 | 寄存器存储建议 |
static | C89 | 静态存储期 / 内部链接 |
extern | C89 | 外部存储期 / 外部链接 |
_Thread_local | C11 新增 | 线程局部存储(旧式拼写) |
thread_local | C23 新增 | 线程局部存储 |
constexpr | C23 新增 | 编译期常量对象 |
- ⑤ 循环控制,如下所示:
| 关键字 | 首次标准 | 含义 / 用途 |
|---|---|---|
for | C89 | for 循环 |
while | C89 | 条件循环 |
do | C89 | do...while 循环的起始关键字 |
- ⑥ 类型限定符,如下所示:
| 关键字 | 首次标准 | 含义 / 用途 |
|---|---|---|
const | C89 | 限制对象不可通过该表达式修改 |
volatile | C89 | 对象可能被外部因素修改 |
restrict | C99 新增 | 限制指针别名关系,帮助优化 |
_Atomic | C11 新增 | 声明原子类型 |
- ⑦ 跳转控制,如下所示:
| 关键字 | 首次标准 | 含义 / 用途 |
|---|---|---|
break | C89 | 退出最内层 switch 或循环 |
continue | C89 | 跳过当前循环的剩余语句 |
goto | C89 | 跳转到指定标签 |
return | C89 | 从函数返回 |
- ⑧ 函数相关,如下所示:
| 关键字 | 首次标准 | 含义 / 用途 |
|---|---|---|
inline | C99 新增 | 内联函数说明 |
_Noreturn | C11 新增 | 函数不会正常返回 |
- ⑨ 内存大小与对齐,如下所示:
| 关键字 | 首次标准 | 含义 / 用途 |
|---|---|---|
sizeof | C89 | 获取对象或类型大小 |
_Alignof | C11 新增 | 获取类型对齐要求(旧式拼写) |
alignof | C23 新增 | 获取类型对齐要求 |
_Alignas | C11 新增 | 指定对齐要求(旧式拼写) |
alignas | C23 新增 | 指定对齐要求 |
- ⑩ 编译期检查与泛型,如下所示:
| 关键字 | 首次标准 | 含义 / 用途 |
|---|---|---|
_Static_assert | C11 新增 | 编译期断言(旧式拼写) |
static_assert | C23 新增 | 编译期断言 |
_Generic | C11 新增 | 编译期泛型选择 |
- ⑪ 布尔值与空指针常量,如下所示:
| 关键字 | 首次标准 | 含义 / 用途 |
|---|---|---|
true | C23 新增 | 布尔真值 |
false | C23 新增 | 布尔假值 |
nullptr | C23 新增 | 空指针常量 |
- ⑫ 类型查询与推导,如下所示:
| 关键字 | 首次标准 | 含义 / 用途 |
|---|---|---|
typeof | C23 新增 | 获取表达式或类型的类型 |
typeof_unqual | C23 新增 | 获取去掉限定符后的类型 |

1.2 标识符
1.2.1 概述
- 凡是程序员自己可以命名的部分就是标识符,如:变量名、函数名、结构体名等。
点我查看 具体细节
- ① 变量名,如下所示:
c
#include <stdio.h>
int main() {
// age 是变量名,是标识符
int age = 0 ;
return 0;
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- ② 函数名,如下所示:
c
#include <stdio.h>
// add 是函数名,是标识符
int add(int a,int b){
return a + b;
}
int main() {
// result 是变量名,是标识符
int result = add(1,2) ;
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
- ③ 结构体名,如下所示:
c
#include <stdio.h>
// Student 是结构体名,是标识符
struct Student {
int age;
};
int main() {
// stu 是变量名,是标识符
struct Student stu = {10};
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14

1.2.2 标识符的命名规则(必须遵守,强制)
- C 语言中的
标识符的命名规则,如下所示:
点我查看 具体细节
- ① 标识符只能使用 26 个英文字母(大小写)、数字(0-9)和下划线(_)。
- ② 标识符不能使用 C 语言的关键字。
- ③ 标识符不能以数字开头。
- ④ 标识符不能包含空格。
- ⑤ 标识符严格区分大小写。
- ⑥ 规则是硬性规定,一旦违反,程序就会在编译过程中报错。

- 示例:合法标识符(✅)
c
#include <stdio.h>
int main() {
// age 是变量名,是标识符,合法 ✅
char name[10] = "abc" ;
// _count 是变量名,是标识符,合法 ✅
int _count = 0 ;
// stu1 是变量名,是标识符,合法 ✅
int stu1 = 0 ;
// student_name 是变量名,是标识符,合法 ✅
char student_name[10] = "Tom" ;
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 示例:非法标识符(❌)
c
#include <stdio.h>
int main() {
// 1age 是变量名,是标识符,非法 ❌ ,原因:标识符不能以数字开头
int 1age = 0 ;
// int 是变量名,是标识符,非法 ❌,原因:标识符不能使用 C 语言的关键字。
char int = '0' ;
// my name 是变量名,是标识符,非法 ❌,原因:标识符不能包含空格。
char my name = "Tom" ;
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1.2.3 标识符的命名规范(柔性规范,非强制)
- C 语言中的
标识符的命名规范,如下所示:
点我查看 具体细节
- ① 常见的 C 语言命名规范,如下所示:
| 类型 | 推荐命名 | 示例 |
|---|---|---|
| 普通变量 | 小写字母 + 下划线 | user_name、student_count |
| 局部变量 | 简短但有意义 | index、count、buffer |
| 函数 | 动词或“动词 + 名词” | get_user()、read_file()、print_info() |
| 结构体变量 | 小写 + 下划线 | user_info |
struct / enum 标签 | 小写 + 下划线较常见 | struct user_info |
| 宏 | 全大写 + 下划线 | MAX_SIZE、DEFAULT_PORT |
| 枚举常量 | 全大写 + 下划线 | STATUS_OK、STATUS_ERROR |
| 全局变量 | 最好加模块前缀 | config_path、net_timeout |
| 布尔含义变量 | is_、has_、can_ 等 | is_ready、has_error |
- ② 编译器并不强制,但为了让代码更清晰、统一、易维护,开发中通常遵循的命名习惯。

- 示例:推荐的写法
c
#include <stdio.h>
int main() {
// name:含义清楚,推荐 👍
char name[10] = "abc";
// student_count:见名知意,snake_case,推荐 👍
int student_count = 0;
// student_name:见名知意,snake_case,推荐 👍
char student_name[10] = "Tom";
// is_ready:布尔含义清楚,推荐 👍
int is_ready = 1;
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 示例:不推荐的写法
c
#include <stdio.h>
int main() {
// a:名字含义不清,不推荐 ⚠️
char a[10] = "abc";
// _count:虽然合法,但不推荐自己以下划线开头 ⚠️
int _count = 0;
// std_cnt:缩写过多,可读性较差,不推荐 ⚠️
int std_cnt = 0;
// studentName:如果项目统一使用 snake_case,这种风格混用不推荐 ⚠️
char studentName[10] = "Tom";
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1.3 总结
- C 语言中的关键字 VS C 语言中的标识符,如下所示:

第二章:常量(🎯)
2.1 概述
常量(Constant)指的是在程序运行过程中,其值不会发生改变的量(数据),如下所示:
c
#include <stdio.h>
int main(void) {
/*
* 10 、3.14 、'A' 、"Hello" 都是常量,这些直接写在代码中的固定值,都是常量。
*/
// 10 是常量
printf("%d\n", 10);
// 3.14 是常量
printf("%.2f\n", 3.14);
// 'A' 是常量
printf("%c\n", 'A');
// "Hello" 是常量
printf("%s\n", "Hello");
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

2.2 常量的分类
2.2.1 概述
- 在 C 语言中,常量的分类,如下所示:

2.2.2 整数常量
2.2.2.1 概念
整数常量指的是没有小数部分的数字,如:10、100 等。示例:
c
#include <stdio.h>
int main(void) {
/* 没有小数部分的数字就是常量 */
printf("%d\n", 10); // 10
printf("%d\n", 100); // 100
printf("%d\n", 0); // 0
printf("%d\n", -20); // -20
printf("%d\n", 2026); // 2026
return 0;
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11

2.2.2.2 不同进制(🌱)
- C 语言中的整数可以使用不同的进制来表示。
提醒
- ① 默认的数字就是十进制。
- ② 八进制需要以 0 开头,数字范围是 0 - 7 的范围,如:012。
- ③ 十六进制需要以 0x 开头,数字范围是 0 - 9 以及 a - z(A-Z),如:0xA。
- ④ 二进制需要以 0b 开头,数字范围是 0 - 1,如:0b1010。
- 示例:
c
#include <stdio.h>
int main(void) {
/*
* C 语言中的整数可以使用不同的进制来表示
* ① 十进制:0-9 的数字,默认,如:10
* ② 八进制:0-7 的数字,以 0 开头,如: 012 表示 8 进制的 10
* ③ 十六进制:0-9 和 A-F 的数字,以 0x 开头,如: 0xA 表示 16 进制的 10
* ④ 二进制:0-1 的数字,以 0b 开头,如: 0b1010 表示 2 进制的 10
*/
printf("%d\n", 10); // 10
printf("%d\n", 012); // 10
printf("%d\n", 0xA); // 10
printf("%d\n", 0b1010); // 10
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

2.2.2.3 整数常量后缀(🌱)
- 整数常量可以通过后缀来指定类型,如下所示:
| 常量后缀 | 实际数据类型 | 有符号占位符 (Signed) 0、正整数和负整数 | 无符号占位符 (Unsigned) 0 和正整数 |
|---|---|---|---|
| 无后缀 | int | %d | - |
| U / u | unsigned int | - | %u |
| L / l | long | %ld | - |
| UL / ul / LU | unsigned long | - | %lu |
| LL / ll | long long | %lld | - |
| ULL / ull / LLU | unsigned long long | - | %llu |
- 示例:
c
#include <stdio.h>
int main(void) {
printf("int = %d\n", 100);
printf("unsigned int = %u\n", 100U);
printf("long = %ld\n", 100L);
printf("unsigned long = %lu\n", 100UL);
printf("long long = %lld\n", 100LL);
printf("unsigned long long = %llu\n", 100ULL);
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13

2.2.3 浮点常量
2.2.3.1 概述
浮点常量指的是带有小数部分的数字,如:3.14、12.5 等。示例:
c
#include <stdio.h>
int main(void) {
/* 浮点常量指的是带有小数部分的数字,如:3.14、12.5 等。 */
printf("%f\n", 3.14);
printf("%f\n", 12.5);
printf("%f\n", 0.5);
printf("%f\n", -10.25);
return 0;
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10

2.2.3.2 默认类型
浮点常量的默认类型是 double 类型。
提醒
在 C 语言中,可以使用 float(单精度)和 double(双进度)来表示不同精度的小数。
- 示例:
c
#include <stdio.h>
int main(void) {
/* 浮点常量指的是带有小数部分的数字,如:3.14、12.5 等。 */
printf("%f\n", 3.14);
printf("%f\n", 12.5);
printf("%f\n", 0.5);
printf("%f\n", -10.25);
return 0;
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10

2.2.3.3 浮点常量后缀(🌱)
- 浮点常量可以通过后缀来指定类型,如下所示:
| 常量后缀 | 实际数据类型 | 占位符(十进制) | 占位符(科学计数法) |
|---|---|---|---|
| 无后缀 | double | %f 或 %lf | %e 或 %le |
| f / F | float | %f | %e |
| l / L | long double | %Lf |
- 示例:
c
#include <stdio.h>
int main(void) {
// 浮点常量
printf("float = %f\n", 3.14f);
printf("double = %f\n", 3.14159265358979);
printf("long double = %Lf\n", 3.14159265358979323846L);
// 科学计数法
printf("double (sci) = %e\n", 3.14159265358979);
// 控制小数位数
printf("double (.2f) = %.2f\n", 3.14159265358979);
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15

2.2.4 字符常量
2.2.4.1 概述
字符常量需要使用单引号('')括起来,单引号中有且仅有一个内容,如:'a'等。示例:
c
#include <stdio.h>
int main(void) {
/*
* 字符常量需要使用单引号('')括起来,
* 单引号中有且仅有一个内容,如:'a'、'1' 等。
*/
printf("%c\n", 'a');
printf("%c\n", 'b');
printf("%c\n", '0');
printf("%c\n", '1');
printf("%c\n", '9');
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14

2.2.4.2 字符常量的本质
- 在计算机中所有的数据都是以二进制的形式存在的,以有符号的整数 10 为例,如下所示:

- 对于 'a' 、'b' 之类的字符,在计算机中分别以什么样的二进制进行存储的呢?
点我查看 具体细节
- ① 如果我们每个人自己给这些字符编一个二进制序列(
编码),就会造成混乱。 - ② 为了方便大家互相通信,后来美国国家标准学会(ANSI)出台了一个标准 ASCII 编码,C 语言中的字符就遵循了 ASCII 编码的方式。

- 完整的 ASCII 编码表,如下所示:
点我查看 具体细节
- ① 字符 A - Z 的 ASCII 码值是 65 - 90。
- ② 字符 a - z 的 ASCII 码值是 97 - 122。
- ③ 大小写字母的字符的 ASCII 码值的差值是 32,如:A 是 65,a 是 97。
- ④ 数字字符 0 - 9 的 ASCII 码值是 48 - 57。
- ⑤ 换行符
\n的 ASCII 码值是 10。 - ⑥ 在这些字符中 ASCII 码值从 0~31 这 32 个字符是不可打印字符,无法打印在屏幕上观察。

- 示例:打印 ASCII 码表中的可见字符
c
#include <stdio.h>
int main(void) {
/* 打印 ASCII 码表中的可见字符 */
for (int i = 32; i < 127; i++) {
printf("%c ", i);
}
return 0;
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11

2.2.4.3 转义字符
2.2.4.3.1 概述
转义字符指的是转换原先字符的含义,如:'n'表示的是字母n,而\n表示换行。
| 转义字符 | 描述 |
|---|---|
\n | 换行 |
\t | 制表符 |
\\ | \ |
\' | ‘ |
\" | “ |
\0 | 空字符 |
| ... | ... |
- 示例:
c
#include <stdio.h>
int main(void) {
/* 转义字符指的是转换原先字符的含义,
* 'n' 表示的是字母 n,而 '\n' 表示换行。
*/
printf("%c\n", '\'');
printf("%c\n", '\"');
printf("c:\\test\\code\\test.c\n");
printf("姓名\t年龄\t身高\n");
printf("许大仙\t16\t1.9\n");
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15

2.2.4.3.2 其它表示形式
- 转义字符也可以使用字符的 8 进制或 16 进来来表示,如下所示:
点我查看 具体细节
- ①
\ddd:ddd表示 1 ~ 3 个八进制的数字,如:\130表示字符X。 - ②
\xdd:dd表示 2 个十六进制数字,如:\x30表示字符0。 - ③
\0:null 字符,代表没有内容,\0就是\ddd这类转义字符的一种,用于字符串的结束标志,其 ASCII 码值是 0。

- 示例:
c
#include <stdio.h>
int main(void) {
// 130 是 8 进制,转换成 10 进制是 88 ,以 88 作为 ASCII 码值的字符是 'X'
printf("%c\n", '\130');
// 0x30 是 16 进制,转换成 10 进制是 48 ,以 48 作为 ASCII 码值的字符是 '0'
printf("%c\n", '\x30');
return 0;
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11

2.2.5 字符串常量
2.2.5.1 概述
字符串常量需要使用双引号("")括起来,如:"abc" 。示例:
c
#include <stdio.h>
int main(void) {
/*
* 字符串常量需要使用双引号("")括起来,如:"abc" 。
*/
printf("%s\n","hello world");
printf("hello world");
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12

2.2.5.2 字符串常量的本质
在 C 语言中,字符串是一段连续存储的字符序列,且必须以空字符
'\0'作为结束标志。示例:
c
#include <stdio.h>
int main(void) {
/*
* 字符串常量需要使用双引号("")括起来,如:"abc" 。
*/
printf("%s\n","hello world");
printf("hello world");
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12

2.2.5.3 字符串的其它表示形式
- 在 C 语言中,可以将字符串放到一个字符数组中,只要其以
\0作为结束标识。
c
char str[] = {'a','b','c', '\0'};1
c
char str[] = "abc"; // 语法糖1
- 示例:
c
#include <stdio.h>
int main(void) {
/*
* 在 C 语言中,可以将字符串放到一个字符数组中,只要其以 \0 作为结束标识。
*/
char str[] = {'a','b','c', '\0'};
char str2[] = "abc"; // 语法糖
printf("%s\n",str);
printf("%s\n",str2);
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15

2.2.6 布尔常量(暂时不需要了解)
布尔常量的值是true或false,其数据类型是bool。
提醒
早期 C 标准没有 bool、true 或 false 关键字,而是约定 0 为 false,非 0 为 true。
- 示例:
c
#include <stdio.h>
int main(void) {
bool is_flag = true;
if (is_flag) {
printf("如果今天下雨,我就不晒衣服");
}else {
printf("如果今天不下雨,我就晒衣服");
}
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13

2.2.7 空指针常量(暂时不需要了解)
空指针常量通常用于给指针变量进行初始化,即:表示该指针变量不指向任何对象。
提醒
空指针常量 通常是 NULL;但是,C23 标准中引入了 nullptr 关键字。
- 示例:
c
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
int main(void) {
int *p = nullptr;
p = (int *)malloc(sizeof(int) * SIZE);
if (p == nullptr) {
perror("malloc error");
return 1;
}
// 初始化数组
for (int i = 0; i < SIZE; i++) {
p[i] = i + 1;
}
// 遍历数组
for (int i = 0; i < SIZE; i++) {
printf("%d ", p[i]);
}
// 释放内存
free(p);
p = nullptr;
return 0;
}1
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
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

2.2.8 枚举常量(暂时不需要了解)
枚举常量是通过enum定义一组整数常量,默认从 0 开始,也可以手动指定。示例:
c
#include <stdio.h>
// 定义枚举类型
enum Color {
// 枚举常量,默认从 0 开始,依次递增
RED,
WHITE,
BLACK
};
int main(void) {
printf("%d\n", RED);
printf("%d\n", WHITE);
printf("%d\n", BLACK);
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

- 示例:
c
#include <stdio.h>
// 定义枚举类型
enum Color {
// 枚举常量,默认从 0 开始,依次递增
RED,
// 枚举常量,可以指定值
WHITE = 10,
BLACK
};
int main(void) {
printf("%d\n", RED);
printf("%d\n", WHITE);
printf("%d\n", BLACK);
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

2.2.9 自定义常量(暂时不需要了解)
2.2.9.1 宏常量
宏常量是使用#define Const Value来定义,其是文本替换(后续讲解)。示例:
c
#include <stdio.h>
#define PI 3.1415926
int main(void) {
printf("PI = %f\n", PI);
printf("area = %f\n", PI * 10 * 10);
return 0;
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11

2.2.9.2 枚举常量
枚举常量是通过enum定义一组整数常量,默认从 0 开始,也可以手动指定。
- 示例:
c
#include <stdio.h>
// 定义枚举类型
enum Color {
// 枚举常量,默认从 0 开始,依次递增
RED,
WHITE,
BLACK
};
int main(void) {
printf("%d\n", RED);
printf("%d\n", WHITE);
printf("%d\n", BLACK);
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

- 示例:
c
#include <stdio.h>
// 定义枚举类型
enum Color {
// 枚举常量,默认从 0 开始,依次递增
RED,
// 枚举常量,可以指定值
WHITE = 10,
BLACK
};
int main(void) {
printf("%d\n", RED);
printf("%d\n", WHITE);
printf("%d\n", BLACK);
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

2.2.9.4 const 常量对象
可以在普通的变量之前加上 const 关键字,该变量就转变为 const 常量对象(有类型)。
示例:
c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const int SIZE = 10;
int *p = nullptr;
p = (int *)malloc(sizeof(int) * SIZE);
if (p == nullptr) {
perror("malloc error");
return 1;
}
// 初始化数组
for (int i = 0; i < SIZE; i++) {
p[i] = i + 1;
}
// 遍历数组
for (int i = 0; i < SIZE; i++) {
printf("%d ", p[i]);
}
// 释放内存
free(p);
p = nullptr;
return 0;
}1
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
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

2.3 常量的运算
2.3.1 概述
- 在 C 语言中,常量之间是可以进行运算的,其运算的类型取决于常量的类型。
2.3.2 整数常量的运算
C 语言支持对
整数常量进行加、减、乘、除、取模(取余数)等运算。示例:
c
#include <stdio.h>
int main(void) {
/* 整数常量之间的运算 */
printf("3 + 4 = %d\n", 3 + 4);
printf("3 - 4 = %d\n", 3 - 4);
printf("3 * 4 = %d\n", 3 * 4);
printf("3 / 4 = %d\n", 3 / 4);
printf("3 %% 4 = %d\n", 3 % 4);
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13

2.3.3 浮点常量的运算
- C 语言支持对
浮点常量进行加、减、乘、除、取模(取余数)等运算。 - C 语言在进行
浮点常量的除法的时候,不会截断小数部分。
- 示例:
c
#include <math.h>
#include <stdio.h>
int main(void) {
/* 浮点常量之间的运算 */
printf("1 + 1.1 = %f\n", 1 + 1.1);
printf("1 - 2.1 = %f\n", 1 - 2.1);
printf("2 * 2.1 = %f\n", 2 * 2.1);
printf("1 / 2.0 = %f\n", 1 / 2.0);
printf("1 %% 2.0 = %f\n", fmod(1, 2.0));
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14

2.3.4 字符常量的运算
在 C 语言中,字符常量可以进行数学运算,如:ASCII 码计算。
示例:
c
#include <stdio.h>
int main(void) {
// 1. 算术运算(使用 ASCII 码值计算)
printf("'A' + 1 = %d\n", 'A' + 1); // 65 + 1 = 66
printf("'a' - 'A' = %d\n", 'a' - 'A'); // 97 - 65 = 32
// 2. 结果可以按整数输出,也可以按字符输出
printf("'A' + 1 作为字符: %c\n", 'A' + 1); // 66 对应的字符是 'B'
// 3. 关系运算(比较 ASCII 码值大小)
if ('a' > 'A') {
printf("小写字母的 ASCII 码大于大写字母\n");
}
// 4. 转义字符也能运算
printf("'\\n' + 1 = %d\n", '\n' + 1); // 10 + 1 = 11
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

2.3.5 布尔常量的运算
2.3.5.1 概述
- 在 C 语言中,布尔常量 用于表示逻辑上的“真”与“假”。
提醒
- ① 从 C23 标准 开始,C 语言引入了
<stdbool.h>头文件,提供了原生的布尔类型bool以及布尔常量true和false。 - ② 要理解布尔常量的运算,首先需要牢记它的 核心本质:在 C 语言底层,
true就是整数1,false就是整数0。
2.3.5.2 逻辑运算(最常用)
逻辑运算用于组合多个条件,其结果只能是true(1) 或false(0)。
| 运算符 | 名称 | 规则 | 示例 | 结果 |
|---|---|---|---|---|
&& | 逻辑与 (AND) | 全真才为真,一假即为假 | true && false | false (0) |
|| | 逻辑或 (OR) | 一真即为真,全假才为假 | true || false | true (1) |
! | 逻辑非 (NOT) | 真变假,假变真 | !true | false (0) |
- 示例:
c
#include <stdio.h>
int main(void) {
/*
* C 语言中打印布尔值通常使用 %d,因为底层它会被当作整数 0 或 1 输出。
*/
printf("a && b = %d\n", true && false); // 输出 0 (false)
printf("a || b = %d\n", true || false); // 输出 1 (true)
printf("!a = %d\n", !true); // 输出 0 (false)
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12

2.5.3.3 关键特性:短路求值
- 逻辑运算中极其重要的特性,能帮我们避免很多 Bug 并优化代码,如下所示:
| 短路求值 | 描述 |
|---|---|
&& 的短路 | 如果左边的表达式为 false,则 不再计算 右边的表达式,直接返回 false。 |
|| 的短路 | 如果左边的表达式为 true,则 不再计算 右边的表达式,直接返回 true。 |
- 示例:
c
#include <stdio.h>
static int check_right() {
printf("右边被计算了!\n");
return true;
}
int main() {
// 1. && 短路:左边是 false,右边不会被执行
if (false && check_right()) {
// ...
}
// 输出:什么都没有(右边没被计算)
// 2. || 短路:左边是 true,右边不会被执行
if (true || check_right()) {
// ...
}
// 输出:什么都没有(右边没被计算)
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

2.5.3.4 算术运算(布尔值当数字用)
- 当布尔值参与算术运算时,会发生
整型提升,结果的类型是int,而不是bool。
提醒
- ① 因为
true是 1,false是 0,所以布尔常量可以直接参与加减乘除等算术运算。 - ② 不建议这种用法,因为很多编程语言压根不支持这种隐式转换。
- 示例:
c
#include <stdio.h>
#include <stdbool.h>
int main() {
// 1. 布尔值相加(常用于统计 true 的个数)
int count = true + true + false + true;
printf("count = %d\n", count); // 输出 3 (1 + 1 + 0 + 1)
// 2. 布尔值相乘
printf("true * false = %d\n", true * false); // 输出 0
// 3. 布尔值作为数组索引或偏移量
int arr[2] = {100, 200};
bool is_second = true;
printf("arr[true] = %d\n", arr[is_second]); // 输出 200 (相当于 arr[1])
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

2.5.3.5 关系运算(产生布尔结果)
关系运算符(
>,<,==,!=等)用于比较两个值,它们的运算结果本身就是布尔常量。示例:
c
#include <stdio.h>
#include <stdbool.h>
int main() {
// 关系运算的结果可以直接赋值给 bool 变量
bool is_greater = (10 > 5);
bool is_equal = (3 == 4);
printf("10 > 5 is %d\n", is_greater); // 输出 1 (true)
printf("3 == 4 is %d\n", is_equal); // 输出 0 (false)
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13

2.4 常量的应用场景
2.4.1 概述
- 常量的应用场景,如下所示:
点我查看 具体细节
- ① 初始化。
- ② 参与计算。
- ③ 进行比较。
- ④ 作为函数参数。
- ⑤ 控制程序逻辑:进来使用 bool、true 或 false 关键字,不建议使用约定。

2.4.2 初始化
常量可以直接用于变量初始化。
示例:
c
#include <stdio.h>
int main() {
// 18 是整数常量,可以用来初始化变量
int age = 18;
printf("age: %d\n", age);
return 0;
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10

2.4.3 参与计算
常量可以出现在表达式中,参与加减乘除等运算。
示例:
c
#include <stdio.h>
int main() {
// 常量可以出现在表达式中,参与加减乘除等运算。
int result = 10 + 20;
printf("result: %d\n", result);
return 0;
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10

2.4.4 进行比较
常量可以和变量进行比较,用于判断条件是否成立。
示例:
c
#include <stdio.h>
int main() {
/* 常量可以和变量进行比较,用于判断条件是否成立。*/
int age = 20;
if (age >= 18) {
printf("成年\n");
}
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12

2.4.5 作为函数参数
调用函数的时候,可以将常量直接传递给函数。
示例:
c
#include <stdio.h>
static int add(int a, int b) {
return a + b;
}
int main() {
printf("%d\n", add(1, 2));
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12

2.4.6 控制程序逻辑
在逻辑判断中,优先使用 bool、true 或 false 来表达真假。
示例:
c
#include <stdio.h>
int main() {
int num = 0;
printf("请输入一个年龄:");
scanf("%d", &num);
if (num >= 18) {
printf("成年\n");
} else {
printf("未成年\n");
}
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
