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++ 编译器。确保您的源文件名为<something>.c
。
【参考方案1】:
你已经接近了。
在 C 中(至少从 1989 年版本的标准开始),malloc
和 realloc
之前的转换是不必要的,因为 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 的理解正确吗?的主要内容,如果未能解决你的问题,请参考以下文章