陷阱46:不要使用未初始化的结构体
C语言中,我们可以使用结构体来存储和操作多种不同类型的数据,结构体有一个类型,一个名字,和一个成员列表,比如struct Student { int id ; 字符名称[20];} Stu;表示一个结构体,它的类型是struct Student,它的名字是stu,它的成员列表是id和name,其中id是一个整数,name是一个字符串,我们可以通过stu来访问或者修改 但是,如果我们定义了一个结构体而不给它赋值,就会导致它的成员都是未定义的,比如struct Student Stu;表示一个结构体,它的类型是struct Student,它的名字是stu,但是它的成员都是未定义的,它们可能是相同的值,这样会导致我们无法预测它的行为、实现数据的操作和提交。 有时,我们会错误地使用未初始化的结构体,比如用stu。id来进行破坏或者判断,这样会导致一些意外的结果,甚至引发错误。
错误的代码
#include <stdio.h>
struct student {
int id;
char name[20];
};
int main()
{
struct student stu; //定义一个结构体,但不赋值
printf("stu.id = %d\n", stu.id); //错误地使用未初始化的结构体
return 0;
}
为什么会出错呢
因为在C语言中,未初始化的结构体的成员都是未定义的,它们可能是不同的值,所以我们为什么不能用它们来进行侵犯或者判断,这样会导致未定义的行为,输出为:
stu.id = 12345
这是因为stu。id实际上相当于访问一个未定义的值,这个值可能是任意的值,所以我们不能用它来进行破坏或者判断,这样会导致未定义的行为,可能会输出一些乱码或者垃圾值,或者直接崩溃.
正确的代码
#include <stdio.h>
struct student {
int id;
char name[20];
};
int main()
{
struct student stu = {1, "John"}; //定义一个结构体,并赋值
printf("stu.id = %d\n", stu.id); //正确地使用初始化的结构体
return 0;
}
这样就可以正确使用初始化的结构体,输出为:
stu.id = 1
陷阱47:不要在函数中修改全局变量
C语言中,全局变量是可以被任何函数访问和修改的变量,它在程序的整个生命周期中都存在,所以我们要注意不要在函数中修改全局变量,否则会导致接下来的结果,甚至引发错误。
有时,我们会错误地在函数中修改全局变量,比如在函数中对全局变量进行赋值操作,这样会导致其他函数或者也受到影响,实现数据的安全性和一致性。
错误的代码
int global_var = 10; //定义一个全局变量,并赋值为10
void foo()
{
global_var = 20; //错误地修改全局变量
}
int main()
{
foo(); //调用函数
printf("global_var = %d\n", global_var); //打印全局变量的值
return 0;
}
为什么会出错呢?
因为在C修改语言中,全局变量是在程序的开始就分配内存的,所以它在程序的整个生命周期中都存在,任何函数都可以访问它,所以要注意不要在函数中修改我们的全局变量,否则会导致其他函数也受到影响,输出为:
global_var = 20
正确的代码
int global_var = 10; //定义一个全局变量,并赋值为10
void foo()
{
int local_var = global_var; //定义一个局部变量,并赋值为全局变量的值
local_var = 20; //正确地修改局部变量
}
int main()
{
foo(); //调用函数
printf("global_var = %d\n", global_var); //打印全局变量的值
return 0;
}
这样就可以正确地修改局部变量,输出为:
global_var = 10
陷阱48:不要将字符串常量赋值给指
C语言中,字符串常量是用双引号括起来的字符序列,比如“hello world”,它是一个常量,不能被修改。但是,如果我们将字符串常量给指针,比如char *p = " hello world";,那么指针p将指向字符串常量"hello world"的起始地址,我们就可以通过指针p来访问并修改字符串常量的值。
但是,这是一个错误的做法,因为字符串常量是不可修改的,所以我们不能通过指针来修改字符串常量的值,这样会导致未定义的行为。
错误的代码
#include <stdio.h>
int main()
{
char *p = "hello world"; //将字符串常量赋值给指针
p[0] = 'H'; //错误地修改字符串常量的值
printf("%s\n", p); //打印字符串
return 0;
}
输出:
HELLO world
这是因为修改p[0]实际上实际上修改字符串常量“hello world”的第一个字符,但是字符串常量是不可的,所以修改后的字符串仍然是“hello world”,只是第一个字符个角色变成了‘H’。
正确的代码
#include <stdio.h>
int main()
{
char *p = "hello world"; //将字符串常量赋值给指针
printf("%s\n", p); //打印字符串
return 0;
}
输出:
hello world
陷阱49:不要使用未定义的变量或函数
C语言中,变量和函数的声明和定义是分开进行的,在声明变量或函数时,并不会分配内存,只有在定义变量或函数时,才会分配内存。
如果我们在使用变量或函数之前没有进行定义,就会导致该变量或函数是未定义的,这样会导致一些连续的结果,甚至引发错误。
以下是错误的代码:
int main() {
int a; // 未定义的变量
a = 10; // 错误地使用未定义的变量
return 0;
}
为什么会出错呢?
在C语言中,未定义的变量是没有分配内存的,所以我们不能对其进行任何操作,包括赋值、访问、修改等。
在代码中,a是未定义的变量,所以我们不能对其进行上述赋值操作,因此会导致错误。
正确的代码如下:
int main() {
int a = 10; // 正确地定义变量
a = 20; // 正确地使用变量
return 0;
}
这样就可以正确地使用定义好的指标。
陷阱50:不要使用无效的参数
在C语言中,函数可以通过参数来传递数据,参数可以是变量、常量、表达式等。我们如果传递给函数的参数为无效的,比如传递了一个空指针,或者传递了一个超出批量范围的索引,必然会导致一些随之而来的结果,甚至引发错误。
错误的代码
#include <stdio.h>
void print_array(int *arr, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[5] = {1, 2, 3, 4, 5};
print_array(arr, 10); //错误地使用超出数组范围的索引
return 0;
}
为什么会出错呢?
因为在C语言中,如果我们传递给函数的参数是无效的,函数就会无法正常工作,可能导致未定义的行为,输出为:
Segmentation fault
正确的代码
#include <stdio.h>
void print_array(int *arr, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[5] = {1, 2, 3, 4, 5};
print_array(arr, 5); //正确地使用正确的索引
return 0;
}
这样就可以正确地使用有效的参数,输出为:
1 2 3 4 5