关于 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.

您的程序未定义有两个原因:

  1. sizenmemb 为零时,calloc() 可能 return NULL。您的程序没有检查 calloc() 的输出,所以当您执行 test[i] 时,您很有可能试图取消引用 NULL 指针——您应该始终检查 calloc()malloc().
  2. 当您调用 malloc()calloc() 时,您本质上是在为数组分配动态内存。您可以使用指针访问数组的元素。但是您无法访问数组过去 的任何内容。也就是说,如果您分配了 n 个元素,您不应该尝试访问第 n+1 个元素 -- 下层用于读取。

以上两项都使您的程序调用未定义的行为。 可能 关于访问除上面列出的第 2 项以外的空对象还有一些未定义的内容,但我不确定。

您应该始终小心未定义的行为,因为当您的程序调用 UB 时,它本质上是 不可预测的。你可能看到编译错误,程序可能给出错误信息,它可能运行 成功,没有任何问题,否则它 可能 擦除硬盘中的每个文件。