关于 calloc 的奇怪事情
strange thing about calloc
我正在编写一些代码并使用了函数 calloc
。
我知道,当传递给该函数的第一个和第二个参数均为零时,该函数将为 0 个元素分配必要的 space,每个元素的大小为 0,但是这里奇怪的是。
即使 n > 0,该程序也能正常工作。为什么会这样?我认为它应该显示错误,因为我正在尝试写入数组中不存在的位置。谢谢!
#include <stdio.h>
#include <stdlib.h>
int main(){
int n;
scanf("%d", &n);
int *test = calloc(0, 0);
for(int i = 0; i < n; i++){
test[i] = 100;
printf("%d ", test[i]);
}
return 0;
}
在 C 中,很多错误 "wrong" 不会显示来自编译器的错误消息。事实上,当您 运行 程序时,您甚至可能看不到错误消息 -- 但另一个人 运行 在另一台计算机上运行您的程序可能会看到错误。
C 中的一个重要概念称为未定义行为。简单来说,这意味着你的程序的行为是不可预测的,但你可以在这个问题中阅读更多关于这个主题的信息:Undefined, unspecified and implementation-defined behavior.
您的程序未定义有两个原因:
- 当
size
或 nmemb
为零时,calloc()
可能 return NULL
。您的程序没有检查 calloc()
的输出,所以当您执行 test[i]
时,您很有可能试图取消引用 NULL
指针——您应该始终检查 calloc()
和 malloc()
.
- 当您调用
malloc()
或 calloc()
时,您本质上是在为数组分配动态内存。您可以使用指针访问数组的元素。但是您无法访问数组过去 的任何内容。也就是说,如果您分配了 n
个元素,您不应该尝试访问第 n+1
个元素 -- 下层用于读取。
以上两项都使您的程序调用未定义的行为。 可能 关于访问除上面列出的第 2 项以外的空对象还有一些未定义的内容,但我不确定。
您应该始终小心未定义的行为,因为当您的程序调用 UB 时,它本质上是 不可预测的。你可能看到编译错误,程序可能给出错误信息,它可能运行 成功,没有任何问题,否则它 可能 擦除硬盘中的每个文件。
我正在编写一些代码并使用了函数 calloc
。
我知道,当传递给该函数的第一个和第二个参数均为零时,该函数将为 0 个元素分配必要的 space,每个元素的大小为 0,但是这里奇怪的是。
即使 n > 0,该程序也能正常工作。为什么会这样?我认为它应该显示错误,因为我正在尝试写入数组中不存在的位置。谢谢!
#include <stdio.h>
#include <stdlib.h>
int main(){
int n;
scanf("%d", &n);
int *test = calloc(0, 0);
for(int i = 0; i < n; i++){
test[i] = 100;
printf("%d ", test[i]);
}
return 0;
}
在 C 中,很多错误 "wrong" 不会显示来自编译器的错误消息。事实上,当您 运行 程序时,您甚至可能看不到错误消息 -- 但另一个人 运行 在另一台计算机上运行您的程序可能会看到错误。
C 中的一个重要概念称为未定义行为。简单来说,这意味着你的程序的行为是不可预测的,但你可以在这个问题中阅读更多关于这个主题的信息:Undefined, unspecified and implementation-defined behavior.
您的程序未定义有两个原因:
- 当
size
或nmemb
为零时,calloc()
可能 returnNULL
。您的程序没有检查calloc()
的输出,所以当您执行test[i]
时,您很有可能试图取消引用NULL
指针——您应该始终检查calloc()
和malloc()
. - 当您调用
malloc()
或calloc()
时,您本质上是在为数组分配动态内存。您可以使用指针访问数组的元素。但是您无法访问数组过去 的任何内容。也就是说,如果您分配了n
个元素,您不应该尝试访问第n+1
个元素 -- 下层用于读取。
以上两项都使您的程序调用未定义的行为。 可能 关于访问除上面列出的第 2 项以外的空对象还有一些未定义的内容,但我不确定。
您应该始终小心未定义的行为,因为当您的程序调用 UB 时,它本质上是 不可预测的。你可能看到编译错误,程序可能给出错误信息,它可能运行 成功,没有任何问题,否则它 可能 擦除硬盘中的每个文件。