C 中的动态数组——我对 malloc 和 realloc 的理解正确吗?

Posted

技术标签:

【中文标题】C 中的动态数组——我对 malloc 和 realloc 的理解正确吗?【英文标题】:Dynamic array in C — Is my understanding of malloc and realloc correct? 【发布时间】:2012-09-22 10:59:55 【问题描述】:

我正在学习如何在 C 中创建动态一维数组。下面的代码尝试执行以下操作:

    使用malloc,创建一个长度为10 的动态数组,其中包含double 类型的值。 将数组的每个条目设置为j/100 以获取j = 0, 1,..., 9。然后打印出来。 使用 realloc 在数组末尾添加一个额外的空条目。 将新条目设置为j/100 并再次打印出每个条目。

测试:

 double* data = (double*)malloc(10*sizeof(double));

 for (j=0;j<10;j++)
 
      data[j]= ((double)j)/100;
      printf("%g, ",data[j]);
 

 printf("\n");

 data = (double*)realloc(data,11*sizeof(double));

 for (j=0;j<11;j++)
 
     if (j == 10) data[j]= ((double)j)/100; 
     printf("%g, ",data[j]);
 

 free((void*) data);

问题

    我编码对了吗?

    我发现使用malloc 的教程没有将(double*) 放在前面。例如,

    int *指针; 指针 = malloc(2*sizeof(int));

这不适用于我在 Visual Studio 2010、Windows 7 上编译。错误消息是

void 类型的值不能分配给int 类型的实体。

为什么它适用于那些教程而不适用于我?我猜是不是因为他们使用的编译器在我的示例中自动为他们填写了(int*)

【问题讨论】:

“void 类型的值不能分配给 int 类型的实体”不是 C 编译器应该产生的错误。问题是您使用的是 C++ 编译器。确保您的源文件名为&lt;something&gt;.c 【参考方案1】:

你已经接近了。

在 C 中(至少从 1989 年版本的标准开始),mallocrealloc 之前的转换是不必要的,因为 C 可以将 void * 类型的值转换为 int * 而无需转换。这对于 C++不是正确,因此根据您遇到的错误,听起来您正在将此代码编译为 C++ 而不是 C。请查看 VS2010 的文档以确定如何编译代码作为C。

以下是我编写malloc 调用的首选风格:

double *data = malloc(10 * sizeof *data);

由于表达式*data 的类型是double,所以sizeof *data 等价于sizeof (double)。这也意味着如果data 的类型发生变化,您不必调整您的malloc 调用。

对于realloc 调用,将结果分配给临时指针值更安全。 realloc如果不能扩展缓冲区,会返回NULL,所以写起来更安全

double *tmp;
...
tmp = realloc(data, 11 * sizeof *data);
if (!tmp)

  // could not resize data; handle as appropriate

else

  data = tmp;
  // process extended buffer

请注意,Microsoft 对 C 语言的支持以 1989 年版本的语言结束;从那时起,该语言标准进行了两次修订,引入了一些新功能并弃用了旧功能。因此,虽然一些 C 编译器支持 C99 特性,如混合声明和代码、可变长度数组等,但 VS2010 不支持。

【讨论】:

谢谢,这很有帮助。 更新:VS2015 支持 C99 + 部分 C11 和 WinXP 目标的选项。所以微软在 2015 年继续支持 ISO C。【参考方案2】:

1) 我编码对了吗?

主要是。但是如果data = (double*)realloc(data,11*sizeof(double)); 失败,data = (double*)realloc(data,11*sizeof(double)); 失去了对分配内存的引用,你应该使用一个临时指针来保存realloc 的返回值并检查它是否是NULL(你还应该检查返回值malloc)。

2) 我发现使用 malloc 的教程没有将 (double*) 放在前面。

在 C 中,malloc 返回一个 void*,它可以隐式转换为任何其他指针类型,因此不需要强制转换(并且由于强制转换可以隐藏错误而被广泛反对)。 Visual Studio 显然将代码编译为需要强制转换的 C++。

【讨论】:

【参考方案3】:

在 C 中,您不应该转换 malloc() 的返回值。

另外,在malloc() 参数中编码类型也是一个坏主意。这是一个更好的方法:

double* data = malloc(10 * sizeof *data);

【讨论】:

这个编译。但是 Visual Studio 2010 警告说“void 类型的值不能用于初始化 double 类型的实体”。可以忽略警告吗? @Legendre 我希望消息说“void * 类型的值不能用于初始化 double * 类型的实体!(注意星号——源和目标都是指针,但类型不同,这是 C++ 编译器必须抱怨的)。

以上是关于C 中的动态数组——我对 malloc 和 realloc 的理解正确吗?的主要内容,如果未能解决你的问题,请参考以下文章

没有malloc的c中的动态内存分配

剖析C动态内存管理 (malloc,calloc,realloc,柔性数组)

C语言中malloc和静态数组最多能开到多大呢

c语言动态数组如何扩充空间

动态内存分配

C语言学习笔记--动态内存分配