第 12 章:初始化 —— 给变量一个'人生起点'
第 12 章:初始化 —— 给变量一个"人生起点"
嗨,未来的 C 语言大师!欢迎来到第 12 章!
你有没有想过,当我们声明一个变量的时候,它在内存里到底是什么状态?是一片空白?还是随机炫彩的"垃圾"数据?
恭喜你,如果你是第一次听说"垃圾值"这个词 —— 今天的课程将是你人生中最重要的"断舍离"教学!
初始化这个问题,说大不大,说小不小。但无数 C 语言老鸟都在这里翻过车,甚至有些隐藏多年的 bug,罪魁祸首就是 —— 忘了初始化。
想象一下:你去买一杯奶茶,结果店员没问你想要什么,直接给你端上了一杯不知道放了多久的"神秘液体"。你喝还是不喝?
变量初始化,就是给变量一个"明确的起点"。没初始化的变量,就像那杯神秘液体 —— 你永远不知道里面是什么(可能是奶茶,也可能是邻居的洗洁精)。
好了,让我们开始这场"初始化"的神奇之旅吧! 🚀
12.1 标量初始化:最基础的"赋值出生证"
什么是标量?
标量(Scalar),听起来高大上对吧?其实就是最简单的一类数据类型——只有一个值的变量。
包括:
- 整型:
int、char、long 等 - 浮点型:
float、double - 指针:
int *、char * 等
初始化语法:int x = 42;
这就是最经典的初始化方式——声明时直接给值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| #include <stdio.h>
int main() {
// 标量初始化示例
int age = 25; // 我的年龄是 25 岁
float height = 1.75f; // 身高 1.75 米(注意 float 要加 f 后缀)
double pi = 3.14159; // 圆周率
char grade = 'A'; // 成绩等级 A
int *ptr = NULL; // 指针初始化为 NULL(空指针)
printf("年龄: %d\n", age); // 输出: 年龄: 25
printf("身高: %.2f\n", height); // 输出: 身高: 1.75
printf("圆周率: %.5f\n", pi); // 输出: 圆周率: 3.14159
printf("等级: %c\n", grade); // 输出: 等级: A
return 0;
}
|
为什么要初始化?
标量初始化就像给变量发一张"身份证"——上面写明了它的姓名(变量名)和出生日期(初始值)。没有身份证的变量,在 C 语言的江湖里就是"黑户"!
1
2
3
4
5
6
7
8
9
10
11
12
13
| #include <stdio.h>
int main() {
// 已经初始化的变量
int initialized = 100;
printf("已初始化: %d\n", initialized); // 输出: 已初始化: 100
// 未初始化的局部变量(危险!)
int uninitialized;
printf("未初始化: %d\n", uninitialized); // 输出: 未初始化: 一个随机垃圾值(每次可能不同!)
return 0;
}
|
警告:上面代码中的 uninitialized 变量,它的值是上一次使用这块内存时留下的"遗迹"——可能是 0,可能是 42,也可能是 -858993460。这就是传说中的"未定义行为"(Undefined Behavior),C 语言标准并没有规定这时候应该是什么值!
12.2 聚合初始化:数组和结构体的"批量出道"
数组初始化
如果说标量初始化是给一个人发身份证,那聚合初始化就是给一整个家族(数组)同时办理户口本!
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
33
| #include <stdio.h>
int main() {
// 方式一:完全初始化——每个位置都指定值
int scores[5] = {90, 85, 88, 92, 78};
// 现在 scores 数组 = {90, 85, 88, 92, 78}
// 方式二:部分初始化——只给前面的赋初值
int partial[5] = {10, 20, 30};
// 现在 partial 数组 = {10, 20, 30, 0, 0}
// 没指定的会自动填 0!
// 方式三:省略长度——让编译器自己数
int auto_size[] = {1, 2, 3, 4, 5};
// 编译器自动把长度设为 5
// 打印验证
printf("完全初始化: ");
for (int i = 0; i < 5; i++) {
printf("%d ", scores[i]); // 输出: 90 85 88 92 78
}
printf("\n");
printf("部分初始化: ");
for (int i = 0; i < 5; i++) {
printf("%d ", partial[i]); // 输出: 10 20 30 0 0
}
printf("\n");
printf("自动长度: %lu\n", sizeof(auto_size) / sizeof(auto_size[0])); // 输出: 5
return 0;
}
|
部分初始化的魔法
敲黑板!这是重点!
当你只给数组的部分元素初始化时,C 语言有个非常贴心的规则:剩余元素自动默认为 0。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| #include <stdio.h>
int main() {
// 只初始化第一个元素
int arr[10] = {42};
printf("arr[0] = %d\n", arr[0]); // 输出: 42
printf("arr[1] = %d\n", arr[1]); // 输出: 0
printf("arr[2] = %d\n", arr[2]); // 输出: 0
// ... 后面所有都是 0!
// 巧用这个特性:全部初始化为 0
int zero[5] = {0}; // 所有元素都是 0!
printf("全部为零: ");
for (int i = 0; i < 5; i++) {
printf("%d ", zero[i]); // 输出: 0 0 0 0 0
}
printf("\n");
return 0;
}
|
小贴士:如果你想快速创建一个全零数组,int arr[100] = {0}; 是最简洁的方式!记住,花括号里只需要写一个 0 就够了。
结构体初始化
结构体(struct)的初始化和数组类似,但可以更灵活——因为结构体有多个成员嘛!
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
| #include <stdio.h>
#include <string.h>
// 定义一个结构体:学生信息
struct Student {
char name[50];
int age;
float gpa;
};
int main() {
// 方式一:按声明顺序初始化(经典方式)
struct Student s1 = {"张三", 20, 3.75f};
printf("学生1: %s, %d岁, GPA: %.2f\n", s1.name, s1.age, s1.gpa);
// 输出: 学生1: 张三, 20岁, GPA: 3.75
// 方式二:指定初始化器(C99,可不按顺序)
struct Student s2 = {.gpa = 3.9f, .name = "李四", .age = 21};
printf("学生2: %s, %d岁, GPA: %.2f\n", s2.name, s2.age, s2.gpa);
// 输出: 学生2: 李四, 21岁, GPA: 3.90
// 方式三:先声明,后赋值
struct Student s3;
strcpy(s3.name, "王五");
s3.age = 19;
s3.gpa = 3.50f;
printf("学生3: %s, %d岁, GPA: %.2f\n", s3.name, s3.age, s3.gpa);
// 输出: 学生3: 王五, 19岁, GPA: 3.50
return 0;
}
|
12.3 指定初始化器(C99):“点名式"赋值
为什么需要指定初始化器?
想象一下这个场景:你要初始化一个数组,其中第 0 个元素是 0,第 5 个元素是 100,其他都是 99。
用传统方法:
1
2
| int arr[10] = {0, 99, 99, 99, 99, 100, 99, 99, 99, 99};
// 写这么多 99,眼睛都花了!
|
有了指定初始化器(C99 引入的特性),你可以"点名"赋值:
1
2
3
| int arr[10] = {[0] = 0, [5] = 100, [1] = 99, [2] = 99, [3] = 99, [4] = 99,
[6] = 99, [7] = 99, [8] = 99, [9] = 99};
// 看起来更清晰了!
|
数组的指定初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| #include <stdio.h>
int main() {
// 指定初始化器:想给谁赋值就写谁的下标
int arr[10] = {[0] = 0, [5] = 100, [9] = 200};
// 其他未指定的元素自动为 0!
printf("arr[0] = %d\n", arr[0]); // 输出: 0
printf("arr[1] = %d\n", arr[1]); // 输出: 0(自动初始化为0)
printf("arr[5] = %d\n", arr[5]); // 输出: 100
printf("arr[9] = %d\n", arr[9]); // 输出: 200
// 混合使用:指定 + 顺序
int mixed[10] = {1, 2, [5] = 50, 3, 4}; // {1, 2, 0, 0, 50, 3, 4, 0, 0, 0}? 不对!
printf("\nmixed 数组内容:\n");
for (int i = 0; i < 10; i++) {
printf("arr[%d] = %d\n", i, mixed[i]);
}
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
33
| #include <stdio.h>
struct Point {
int x;
int y;
int z;
};
struct Rectangle {
struct Point top_left;
struct Point bottom_right;
};
int main() {
// 乱序初始化结构体?不存在的!
struct Point p = {.y = 10, .x = 5, .z = 15};
printf("点坐标: (%d, %d, %d)\n", p.x, p.y, p.z);
// 输出: 点坐标: (5, 10, 15)
// 嵌套结构体的指定初始化
struct Rectangle rect = {
.top_left = {.x = 0, .y = 10},
.bottom_right = {.x = 20, .y = 0}
};
printf("矩形左上: (%d, %d)\n", rect.top_left.x, rect.top_left.y);
// 输出: 矩形左上: (0, 10)
printf("矩形右下: (%d, %d)\n", rect.bottom_right.x, rect.bottom_right.y);
// 输出: 矩形右下: (20, 0)
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
| #include <stdio.h>
// 假设我们要初始化一个星期的编码映射
int main() {
// 传统方式:数位置
// int day_code[7] = {1, 2, 3, 4, 5, 6, 7}; // Monday=1, Tuesday=2, ...
// 指定初始化器:清晰明了!
int day_code[7] = {
[0] = 1, // Monday
[1] = 2, // Tuesday
[2] = 3, // Wednesday
[3] = 4, // Thursday
[4] = 5, // Friday
[5] = 6, // Saturday
[6] = 7 // Sunday
};
// 现在你想知道 Friday 对应几?直接看 [4] = 5,一目了然!
printf("Friday code: %d\n", day_code[4]); // 输出: 5
// 如果哪天顺序变了(比如周日变成第一天)
// 只需要改一处,不用改整个数组!
return 0;
}
|
12.4 复合字面量(C99):匿名变量的大招
什么是复合字面量?
复合字面量(Compound Literal)是 C99 引入的一个"黑科技”——它允许你在表达式中直接创建一个数组或结构体,而不用先给它们起个名字。
听起来有点抽象?让我用生活中的例子解释:
正常情况下,你去奶茶店点单,要先说"我要一杯奶茶"(声明变量),然后店员给你做(赋值)。但复合字面量就像是——你直接喊"给我一杯奶茶,多加珍珠!“然后当场喝掉,不用给它起名字。
数组的复合字面量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| #include <stdio.h>
int main() {
// 普通方式:先声明,再赋值
int arr1[3] = {1, 2, 3};
// 复合字面量:直接创建匿名数组
int *ptr = (int[]){4, 5, 6}; // (int[]) 是类型标识,后面跟初始化列表
// 使用指针访问
printf("ptr[0] = %d\n", ptr[0]); // 输出: 4
printf("ptr[1] = %d\n", ptr[1]); // 输出: 5
printf("ptr[2] = %d\n", ptr[2]); // 输出: 6
// 复合字面量的常用场景:作为函数参数
int sum = 0;
int values[3] = {10, 20, 30};
for (int i = 0; i < 3; i++) {
sum += values[i];
}
printf("sum = %d\n", sum); // 输出: 60
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
| #include <stdio.h>
struct Point {
int x;
int y;
};
void print_point(struct Point p) {
printf("点坐标: (%d, %d)\n", p.x, p.y);
}
int main() {
// 普通方式:先命名,再传参
struct Point p1 = {10, 20};
print_point(p1);
// 输出: 点坐标: (10, 20)
// 复合字面量:直接作为参数传递,不用命名!
print_point((struct Point){30, 40});
// 输出: 点坐标: (30, 40)
// 还可以用指定初始化器
print_point((struct Point){.y = 50, .x = 60});
// 输出: 点坐标: (60, 50)
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
33
34
35
36
37
38
| #include <stdio.h>
struct Matrix {
int rows;
int cols;
int data[3][3];
};
void print_matrix(struct Matrix m) {
printf("矩阵 (%dx%d):\n", m.rows, m.cols);
for (int i = 0; i < m.rows; i++) {
for (int j = 0; j < m.cols; j++) {
printf("%4d ", m.data[i][j]);
}
printf("\n");
}
}
int main() {
// 场景一:临时创建一个矩阵用于计算
print_matrix((struct Matrix){
.rows = 3,
.cols = 3,
.data = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
});
// 输出一个 3x3 矩阵
// 场景二:函数返回临时结构体
struct Point create_point(int x, int y) {
return (struct Point){x, y}; // 直接返回复合字面量!
}
struct Point center = create_point(100, 200);
printf("中心点: (%d, %d)\n", center.x, center.y);
// 输出: 中心点: (100, 200)
return 0;
}
|
12.5 隐式初始化规则:内存的"潜规则”
这是 C 语言中最容易踩坑的地方之一!
想象一下,你去酒店入住,前台说"房间已经给你留好了"。结果你推开门,发现里面住着陌生人(垃圾值)!这就是未初始化局部变量的恐怖之处。
全局变量和静态变量的"特殊待遇"
在 C 语言中,全局变量(在函数外部声明)和静态变量(用 static 关键字声明)会自动被初始化为 零。
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
| #include <stdio.h>
// 全局变量(自动初始化为 0)
int global_int;
float global_float;
char global_char;
int *global_ptr;
void test_static() {
// 静态变量(自动初始化为 0)
static int static_int;
static float static_float;
printf("函数内的静态变量:\n");
printf(" static_int = %d\n", static_int); // 输出: 0
printf(" static_float = %.2f\n", static_float); // 输出: 0.00
}
int main() {
printf("全局变量(自动零初始化):\n");
printf(" global_int = %d\n", global_int); // 输出: 0
printf(" global_float = %.2f\n", global_float); // 输出: 0.00
printf(" global_char = '%c'\n", global_char); // 输出: ''
printf(" global_ptr = %p\n", (void*)global_ptr); // 输出: (nil)
test_static();
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
33
34
35
| #include <stdio.h>
#include <time.h>
#include <stdlib.h>
void show_garbage() {
// 局部变量(不初始化!)
int x;
int y;
int z;
// 打印"垃圾值"
printf("局部的 x = %d\n", x);
printf("局部的 y = %d\n", y);
printf("局部的 z = %d\n", z);
}
int main() {
// 全局变量
int global = 999;
printf("全局变量 global = %d(永远是 0)\n", global);
// 局部变量 —— 危险地带!
int local;
printf("局部变量 local = %d(可能是任何值!)\n", local);
// 演示垃圾值的"随机性"
printf("\n连续调用三次 show_garbage():\n");
show_garbage();
printf("---\n");
show_garbage();
printf("---\n");
show_garbage();
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
| #include <stdio.h>
int main() {
// 错误示例 1:累加器忘记初始化
int sum;
int numbers[] = {1, 2, 3, 4, 5};
// 以为 sum 初始值是 0,实际是垃圾值!
for (int i = 0; i < 5; i++) {
sum += numbers[i]; // sum 未初始化,可能是任意值
}
printf("sum = %d(应该是 15,但如果 sum 初始是 10086...)\n", sum);
// 正确做法:初始化为 0
sum = 0; // 必须初始化!
for (int i = 0; i < 5; i++) {
sum += numbers[i];
}
printf("sum = %d(正确!应该是 15)\n", sum);
// 错误示例 2:指针忘记初始化
int *ptr;
// printf("%d\n", *ptr); // 危险!ptr 没有初始化,指向未知地址!
// 正确做法
int value = 42;
ptr = &value; // 让指针指向一个有效的地址
printf("*ptr = %d(安全!)\n", *ptr); // 输出: 42
return 0;
}
|
初始化规则总结表
| 变量类型 | 位置 | 初始值 | 举例 |
|---|
| 全局变量 | 函数外部 | 零 (0) | int g_x; |
| 静态变量 | 函数内部 | 零 (0) | static int s_x; |
| 局部变量 | 函数内部 | 垃圾值! | int l_x; |
| 指针变量 | 函数内部 | 垃圾值(野指针)! | int *p; |
12.6 字符串数组初始化:字符数组的特殊待遇
字符数组 vs 普通数组
字符串在 C 语言中是一个特殊的存在——它是 char 类型的数组,但有一些"专属特权"。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| #include <stdio.h>
int main() {
// 方式一:逐个字符初始化(普通数组方式)
char s1[] = {'H', 'e', 'l', 'l', 'o', '\0'}; // 必须手动加 '\0'!
// 方式二:用字符串字面量初始化(字符串专属方式!)
char s2[] = "Hello"; // 自动包含 '\0',不用手动写
printf("s1 = %s\n", s1); // 输出: Hello
printf("s2 = %s\n", s2); // 输出: Hello
// 长度对比
printf("s1 长度: %lu\n", sizeof(s1) / sizeof(char)); // 输出: 6 (5个字符 + '\0')
printf("s2 长度: %lu\n", sizeof(s2) / sizeof(char)); // 输出: 6 (5个字符 + '\0')
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
| #include <stdio.h>
#include <string.h>
int main() {
// 姿势一:指定大小,多余的位置自动填 '\0'
char s1[10] = "Hi";
printf("s1: "); for (int i = 0; i < 10; i++) printf("[%c]", s1[i]);
// 输出: s1: [H][i][\0][\0][\0][\0][\0][\0][\0][\0]
// 姿势二:自动计算长度
char s2[] = "Hello";
printf("\ns2 大小: %lu (自动计算)\n", sizeof(s2)); // 输出: 6
// 姿势三:字符逐个初始化(必须自己加 '\0')
char s3[6] = {'W', 'o', 'r', 'l', 'd', '\0'};
// 姿势四:只初始化第一个字符,其余自动为 '\0'
char s4[5] = {'A'};
printf("s4: ");
for (int i = 0; i < 5; i++) {
printf("[%d]", s4[i]); // 输出: [65][0][0][0][0]
}
return 0;
}
|
字符串数组的经典错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| #include <stdio.h>
int main() {
// 错误:忘记 '\0' 结束符
char bad[] = {'H', 'e', 'l', 'l', 'o'}; // 没有 '\0'!
// printf("%s\n", bad); // 危险!会一直打印直到遇到 '\0'!
// 正确:手动添加 '\0'
char good[] = {'H', 'e', 'l', 'l', 'o', '\0'};
// 最推荐:使用字符串字面量
char best[] = "Hello"; // 自动包含 '\0'
printf("字符串: %s\n", best); // 输出: Hello
return 0;
}
|
12.7 const 与初始化:常量必须"一出生就定型"
const 是什么?
const 是 C 语言中用于声明"常量"的关键字。一旦一个变量被 const 修饰,它就再也不能被修改了。
1
2
3
4
5
6
7
8
9
10
| #include <stdio.h>
int main() {
const int CONSTANT_VALUE = 100;
// CONSTANT_VALUE = 200; // 错误!不能修改 const 变量!
printf("常量值: %d\n", CONSTANT_VALUE); // 输出: 100
return 0;
}
|
const 变量的初始化规则
const 变量必须在声明时初始化! 因为一旦声明为 const,就再也不能赋值了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| #include <stdio.h>
int main() {
// 正确:声明时初始化
const int a = 10;
const float b = 3.14f;
const char c = 'A';
printf("a=%d, b=%.2f, c=%c\n", a, b, c);
// 错误:先声明后初始化(编译错误!)
// const int d; // 错误!const 变量必须在声明时初始化!
// d = 20;
// const 指针的初始化
int value = 42;
const int *ptr1 = &value; // 指向常量的指针
int *const ptr2 = &value; // 常量指针(指针本身不能变)
printf("*ptr1=%d, *ptr2=%d\n", *ptr1, *ptr2);
return 0;
}
|
静态初始化 vs 运行时初始化
这是理解 const 行为的关键!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| #include <stdio.h>
// 场景一:const 全局变量必须在编译时就能确定值
// 编译器需要在编译阶段就把值"刻进"二进制文件里
const int COMPILE_TIME_VALUE = 123; // 编译时已知 → OK
// const int RUN_TIME_VALUE; // 错误!运行时才能确定 → 不行!
int main() {
// 场景二:const 局部变量可以是运行时计算的结果
int input;
printf("请输入一个数字: ");
scanf("%d", &input);
const int run_time = input; // 运行时才知道值 → OK
printf("运行时 const 值: %d\n", run_time);
// 注意:const 只保证"不能修改",不保证"编译时确定"
return 0;
}
|
const 的真正意义
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
| #include <stdio.h>
// 用 const 提高代码可读性和安全性
// 方式一:不用 const
double calculate_circle_area(double radius) {
// radius 能改吗?不知道!
// 会不会被不小心改掉?不知道!
return 3.14159 * radius * radius;
}
// 方式二:用 const 声明"这个参数我不会改"
double calculate_circle_area_const(double radius) {
const double pi = 3.14159; // 这个 pi 不会变
const double r = radius; // 这个 r 也不会变(只是复制)
// radius = 999; // 如果取消注释,编译错误!保护了原始数据
return pi * r * r;
}
int main() {
printf("面积: %.2f\n", calculate_circle_area_const(5.0));
// 输出: 面积: 78.54
return 0;
}
|
本章小结
恭喜你完成了"初始化"这一章的学习!让我们来回顾一下今天学到的核心知识点:
🎯 关键知识点
标量初始化:在声明时直接给单一值变量赋值,如 int x = 42;。未初始化的局部变量是"垃圾值"——一个完全不可预测的随机数。
聚合初始化:用于数组和结构体。数组部分初始化时,未指定的元素自动为零;结构体可以按顺序或用指定初始化器(C99)不按顺序初始化。
指定初始化器(C99):使用 [index] 或 .member 语法精准赋值,如 int arr[5] = {[2] = 10};,让代码更清晰,不易出错。
复合字面量(C99):创建匿名数组或结构体,如 (int[]){1, 2, 3},非常适合临时数据或函数参数传递。
隐式初始化规则:全局变量和静态变量自动初始化为 0,但局部变量不会自动初始化,必须手动赋值!这是 C 语言最常见的 bug 来源之一。
字符串数组初始化:char s[] = "hello"; 是最简洁的方式,编译器会自动处理 '\0' 结束符。
const 与初始化:const 变量必须在声明时初始化(编译时常量),或者在运行时通过计算赋值(但一旦赋值就不能再改)。
💡 编程习惯建议
养成为每个变量显式初始化的好习惯! 即使你知道它会被后续赋值,提前初始化也是一个好习惯,能让代码更安全,也让阅读代码的人更清楚你的意图。
⚠️ 避坑提醒
- 永远不要假设局部变量会自动初始化为零
- 永远不要假设别人会记得初始化变量
- 使用
-Wall -Wextra 编译器警告标志,它能帮你发现未初始化的变量
第 12 章:初始化 —— 给变量一个"人生起点" 到此结束!
下一章我们将探讨 C 语言的更多高级特性。继续保持这份热情,你已经比 90% 的 C 语言学习者更懂得如何写出安全的代码了! 💪
记住:一个好的起点,决定了变量的一生!