如何解决如何在C中将数组的大小加倍
我有一个程序,该程序从动态数组中存储的最少10个响应(int)开始,但如果需要,应使用void函数将其大小加倍。
typedef int* Statistician;
int main(int argc,char** argv) {
Statistician answer;
answer=(int*)calloc(SIZE,sizeof(int));
add(answer,&SIZE);
}
void add(Statistician answer,int *SIZE){
answer=(int*)calloc(*SIZE * 2,sizeof(int));
}
这是将其大小增加一倍的正确方法吗? 我需要在正确的方向上轻推一下。
解决方法
最大的误解是您将answer
的值传递给add()
,因此add()
收到了副本,并且answer
中对add()
的任何更改都丢失了在函数返回时。而且由于类型为void
,所以您没有机会对在调用方中看到的answer
进行更改(此处为main()
)
要解决此问题,请将answer
的地址传递到add()
,以便在realloc()
而不是calloc()
增大大小时使用原始指针地址,例如
void add(Statistician *answer,int *SIZE){
void *tmp = realloc(*answer,*SIZE * 2 * sizeof **answer);
if (!tmp) {
perror ("add-realloc-answer");
return;
}
*answer = tmp;
/* optional - zero new memory mimicking calloc() */
memset (*answer + *SIZE,*SIZE * sizeof **answer);
*SIZE *= 2;
}
您致电添加方式:
add(&answer,&SIZE);
(请注意,SIZE
必须是正确初始化的全局int
。实际上应在main()
中将其替换为开头的size_t size = SIZE;
,然后将指针传递给{ {1}}。
由于您键入了指针而使您感到困惑,请参阅Is it a good idea to typedef pointers?。此外,在C语言中,无需强制转换size
(或malloc
或calloc
)的返回值,这是不必要的。参见:Do I cast the result of malloc?
消除指针的realloc
要使指针的间接访问级别保持明显,避免指针的typedef
并在需要类型的地方简单地使用typedef
就容易得多。进行这些更改,并将int*
与局部变量SIZE
一起使用,以确保作为参数传递的任何局部副本都不会与全局变量冲突。添加简单的例程来填充每个整数并在考虑size
之前/之后验证每个整数,首选方法是:
add()
注意:由于#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 128
int *add (int **answer,size_t *size)
{
/* always realloc to a temporary pointer,when realloc fails
* it returns NULL and if you assign to original pointer you
* create a memory leak with loss of your stored data.
*/
void *tmp = realloc(*answer,*size * 2 * sizeof **answer);
if (!tmp) { /* validate every allocation */
perror ("add-realloc-answer");
return NULL;
}
*answer = tmp; /* assign reallocated block to pointer */
/* optional - zero new memory mimicking calloc() */
memset (*answer + *size,*size * sizeof **answer);
*size *= 2; /* update size only on success */
return *answer; /* return pointer indicating success */
}
int main(void) {
int *answer;
size_t size = SIZE;
answer = calloc(size,sizeof *answer); /* allocate */
if (answer == NULL) { /* validate */
perror ("calloc-answer");
return 1;
}
for (size_t i = 0; i < size; i++) /* fill memory */
answer[i] = i;
if (!add(&answer,&size)) /* add and validate return */
fputs ("realloc failed,using original size.\n",stderr);
else
printf ("realloc succeeded -- %zu integers.\n",size);
for (size_t i = size/2; i < size; i++) /* fill new memory */
answer[i] = i;
for (size_t i = 0; i < size; i++) /* validate complete block */
if (i != (size_t)answer[i])
fprintf (stderr,"error: answer[%zu] != %d\n",i,answer[i]);
free (answer); /* free allocated memory */
}
可能会失败,因此您的函数需要一种将成功或失败传达回调用方的方法。选择有意义的返回类型(realloc()
int
或指针0/1
等)
使用/输出示例
valid address/NULL
内存使用/错误检查
在您编写的任何动态分配内存的代码中,对于任何分配的内存块,您都有2个职责:(1)始终保留指向起始地址的指针因此,(2)不再需要它时可以释放。
当务之急是使用一个内存错误检查程序来确保您不会尝试访问内存或在分配的块的边界之外/之外写,尝试读取或基于未初始化的值进行条件跳转,最后,以确认您释放了已分配的所有内存。
对于Linux,$ ./bin/realloc-add
realloc succeeded -- 256 integers.
是正常选择。每个平台都有类似的内存检查器。它们都很容易使用,只需通过它运行程序即可。
valgrind
始终确认已释放已分配的所有内存,并且没有内存错误。
如果您还有其他问题,请告诉我。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。