C 调整函数中结构数组的大小
我想动态地将新元素添加到结构数组中。我添加了一个最小的示例,说明了segfults。我想我必须向函数传递一个指针C 调整函数中结构数组的大小,c,arrays,dynamic,struct,C,Arrays,Dynamic,Struct,我想动态地将新元素添加到结构数组中。我添加了一个最小的示例,说明了segfults。我想我必须向函数传递一个指针structdata**arr,才能正确地重新分配和添加新元素,但我一直无法正确地执行此操作 #include <string.h> #include <stdlib.h> #include <stdio.h> struct data { char s[10]; int arr[10]; }; void add_one_eleme
structdata**arr
,才能正确地重新分配和添加新元素,但我一直无法正确地执行此操作
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
struct data {
char s[10];
int arr[10];
};
void add_one_element(struct data *arr, int *num_elements)
{
/*increment counter*/
*num_elements +=1;
arr = realloc(arr, *num_elements * sizeof(struct data));
strcpy(arr[*num_elements-1].s, "ABC");
for(int i = 0; i < 10; i++)
arr[*num_elements-1].arr[i] = i;
}
int main()
{
struct data *arr = NULL;
int num_elements = 0;
add_one_element(arr, &num_elements);
printf("arr.s = %s\n", arr[num_elements-1].s);
for(int i = 0; i < 10; i++)
printf("arr[%d].arr[%d] = %d\n", num_elements-1, i, arr[num_elements-1].arr[i]);
free(arr);
return 0;
}
您需要将
结构数据**
传递给函数,这是正确的。您可以按如下方式进行操作:
void add_one_element(struct data **arr, int *num_elements)
{
/*increment counter*/
*num_elements +=1;
*arr = realloc(*arr, *num_elements * sizeof(struct data));
strcpy((*arr)[*num_elements-1].s, "ABC");
for(int i = 0; i < 10; i++)
(*arr)[*num_elements-1].arr[i] = i;
}
由于C按值传递,因此在没有引用的情况下无法更改调用方的变量值。在C语言中,这是通过取消引用指向函数需要更改的变量的指针来实现的。因此,需要将指针传递给指针变量
void add_one_element(struct data **arr, int *num_elements)
{
struct data *tmp;
int tmp_num = *num_elements + 1;
/*increment counter*/
tmp = realloc(*arr, tmp_num * sizeof(struct data));
if (tmp == NULL) {
/* XXX: handle the error */
return;
}
strcpy(tmp[tmp_num-1].s, "ABC");
for(int i = 0; i < 10; i++)
tmp[tmp_num-1].arr[i] = i;
*arr = tmp;
*num_elements = tmp_num;
}
(在编辑的更改中,未取消对指针变量的引用。)
realloc
可能返回NULL,在这种情况下,原始指针未被释放。因此,您需要在单独的变量中捕获并测试结果或realloc
void add_one_element(struct data **arr, int *num_elements)
{
struct data *tmp;
int tmp_num = *num_elements + 1;
/*increment counter*/
tmp = realloc(*arr, tmp_num * sizeof(struct data));
if (tmp == NULL) {
/* XXX: handle the error */
return;
}
strcpy(tmp[tmp_num-1].s, "ABC");
for(int i = 0; i < 10; i++)
tmp[tmp_num-1].arr[i] = i;
*arr = tmp;
*num_elements = tmp_num;
}
void添加一个元素(结构数据**arr,int*num元素)
{
结构数据*tmp;
int tmp_num=*num_元素+1;
/*增量计数器*/
tmp=realloc(*arr,tmp_num*sizeof(结构数据));
if(tmp==NULL){
/*XXX:处理错误*/
返回;
}
strcpy(tmp[tmp_num-1].s,“ABC”);
对于(int i=0;i<10;i++)
tmp[tmp_num-1].arr[i]=i;
*arr=tmp;
*num_elements=tmp_num;
}
realloc在main
中设置局部变量的地址而不是arr
,将指针传递给指针:void add\u one\u元素(struct data**arr,int*num\u元素)
和add\u one\u元素(&arr,&num\u元素)代码>在调试器中仔细检查代码会很快向您指出问题。类似于arr=realloc(arr,…
是非常糟糕的做法!如果realloc
返回空指针怎么办?您丢失了数组。第一件事是进行正确的错误处理!请注意,使用realloc()将一个指针重复添加到数组中
通常会随着时间的推移产生二次性能,因为它必须将以前的所有条目复制到新位置。通常的技术是(a)记录分配的条目数和正在使用的条目数,以及(b)当您需要分配更多时,将分配的条目数增加一倍。如果添加完成后,有足够的额外分配空间来保证添加,则可以使用收缩的realloc()
返回未使用的空间。“够了”-视情况而定;也许可以考虑256字节或更多。或者,如果以realloc故障表示可能即将发生无法恢复的故障的实现为目标,realloc
返回null,则可以简单地强制异常终止。@supercat:这是一个有效的决定我更希望将失败记录下来并传播回调用方,以决定是否需要终止。如果程序在内存不足的情况下异常终止,则可以满足程序的要求;如果程序写入memo,则不能满足程序的要求如果没有,则保证成功或异常终止的分配API比要求调用方检查每个调用是否可能失败的API更容易满足这些要求。此外,一些虚拟内存系统仅在如果代码进行了大量分配,并最终放弃了这些分配,而留下了大量未使用的数据块,则这种设计可以很好地工作,但不可能从内存不足的情况下可靠地恢复。如果与内存不足故障导致程序在解引用看似有效的指针时死亡的情况相比,返回null的情况不太常见。尝试优雅地处理前者没有多大意义。@supercat:也有例外,我只是简单地说明我更喜欢什么。
void add_one_element(struct data **arr, int *num_elements)
{
struct data *tmp;
int tmp_num = *num_elements + 1;
/*increment counter*/
tmp = realloc(*arr, tmp_num * sizeof(struct data));
if (tmp == NULL) {
/* XXX: handle the error */
return;
}
strcpy(tmp[tmp_num-1].s, "ABC");
for(int i = 0; i < 10; i++)
tmp[tmp_num-1].arr[i] = i;
*arr = tmp;
*num_elements = tmp_num;
}