取自菜鸟教程 如需更详细请移步C语言未定义常见错误
C 未定义行为(Undefined behavior)
在 C 语言中,“undefined behavior”(未定义行为)是指程序的行为在 C 语言标准中没有明确定义,因此可以表现为任何结果。
这意味着当程序出现未定义行为时,它可能会产生不可预测的结果,包括程序崩溃、数据损坏、安全漏洞,甚至可能看起来正常运行。
未定义行为是C语言中一个重要的概念,因为它涉及到程序的正确性和安全性。
以下是一些常见的可能导致未定义行为的情况:
数组越界
当我们尝试访问数组的越界元素时,即访问数组的第0个元素之前或数组长度之后的元素时,编译器无法确定访问到的内存空间中存储的是什么内容,因此会导致未定义行为。例如:
int arr[3] = {1, 2, 3};
printf(“%d\n”, arr[5]); // 越界访问,结果未定义
解引用空指针
当我们尝试对空指针进行解引用操作时,编译器无法确定要访问的内存空间中存储的内容,因此会导致未定义行为。例如:
int *ptr = NULL;
printf(“%d\n”, *ptr); // 解引用空指针,结果未定义
未初始化的局部变量
当我们使用未初始化的局部变量时,其值是未定义的,因此会导致未定义行为。例如:
int x;
printf(“%d\n”, x); // x 未初始化,结果未定义
浮点数除以零
当我们尝试对浮点数进行除以零的操作时,结果是未定义的。例如:
float x = 1.0;
float y = x / 0.0; // 浮点数除以零,结果未定义
整数除以零
当我们尝试对整数进行除以零的操作时,结果是未定义的。例如:
int x = 10;
int y = x / 0; // 整数除以零,结果未定义
符号溢出
当整数运算导致结果超出了整数类型能表示的范围时,结果是未定义的。例如:
signed char x = 127;
x = x + 1; // signed char 溢出,结果未定义
位移操作数太大
当执行位移操作时,位移的位数大于或等于操作数的位数时,结果是未定义的。例如:
int x = 1;
int y = x << 32; // 位移操作数太大,结果未定义
错误的类型转换
当我们进行不安全的类型转换时,结果是未定义的。例如:
int *ptr = (int *)malloc(sizeof(int));
float *fptr = (float *)ptr; // 错误的类型转换,结果未定义
内存越界
当我们向已经释放或未分配的内存写入数据时,结果是未定义的。例如:
int *ptr = (int *)malloc(sizeof(int));
free(ptr);
*ptr = 10; // 内存越界,结果未定义
未定义的浮点数行为
比如比较两个 NaN(非数字)值是否相等,这是未定义的行为。例如:
float x = sqrt(-1);
float y = sqrt(-1);
if (x == y) {
printf(“NaN values are equal\n”);
}
其他未定义的行为:
使用未定义的浮点数特性:依赖于特定硬件或实现的浮点数行为,如浮点数的精度或舍入行为。
函数参数数量不匹配:调用函数时提供的参数数量与函数定义不匹配,如 printf(“%s %d”, “Name”)。
修改字符串字面量:尝试修改字符串字面量的内容,如 char *str = “Hello”; str[0] = ‘h’;。
使用未定义的程序状态:依赖于未定义的程序状态,如全局变量的初始值。
违反严格的语法规则:违反 C 语言的严格语法规则,如使用未声明的标识符。
多线程中的竞态条件:在多线程环境中,未同步的共享资源访问可能导致未定义行为。
使用未定义的标准库函数行为:某些标准库函数在特定条件下的行为可能是未定义的,如 fscanf() 在未匹配到任何输入时的行为。