我无法在运行时确定数组大小,因为它将具有依赖性。所以我需要为一个元素做内存分配。就像我可以说的链接列表一样。
如何在整数数组中执行此操作?
答案 0 :(得分:1)
我认为你说你想要一次'成长'一个数组元素。
对于整数数组(*), realloc()
是C中的一个选项。
size_t n=0;//Length of array.
int* arr=NULL;
//Some code...
//Now we want to grow our array
//This is probably in a loop or called in a function from a loop (not shown).
++n;
int* temp=realloc(arr,n*sizeof(int));
if(temp==NULL){
free(arr);
return 1;//Error...
}
arr=temp;
//More code....
//Now we're done with arr.
free(arr);
第一次传递arr
为NULL
,realloc(NULL,..)
就像malloc()
一样。
但是在arr
不是NULL
的后续传递中,realloc
会尝试在适当的位置增长数组(如果内存在其末尾可用)。如果没有,它会尝试在其他地方分配空间,然后复制现有数据并释放旧位置。
如果它无法重新分配,则不会执行任何操作并返回NULL
,因此您有责任释放该空格(free(arr)
)。
注意:始终将realloc()
的返回值分配给临时变量(即不是第一个参数)。
否则,如果分配失败,则泄漏现有内存。
realloc
是减少生成数组所需的分配和复制量的快速技巧 - 另类。
如果这不够有效,那么普通模型就是跟踪“容量”和“长度”这样的事情。
const size_t chunk=10;
size_t cap=0;
size_t n=0;
int* arr=NULL;
++n;
if(n>cap){
cap+=chunk;
int* temp=realloc(arr,cap);
if(temp==NULL){
free(arr);
return 1;//Error
}
}
//Later...
free(arr);
这样做的好处是,您可以调整调整重新分配频率的“备用”开销。另一个策略是cap=cap*2;
,但显然空间趋于成倍增长!可以写一本关于这个经典战略的书。通常可以在一次点击中为大多数现实案例分配足够的内容,但仍处理特殊情况。
如果您知道阵列现在是全尺寸的,那么您还可以选择分配回来恢复可用空间。
如果不明显,如果移动了数组,则必须重定向指向它或指向它的任何指针。这是仅用[.]
索引到它的论据。在进行重定向之前,您需要保留旧位置。 ptr=temp+(ptr-arr)
使ptr
指向指向的元素ptr
的新位置。
这是Java ArrayList
中的标准方法和std::vector<>
的大多数实现。这是一个工程妥协。数组的好处(按索引进行O(1)随机访问)和链表(O(1)增长)。
它渐近线性但在实际情况下提供了很大的好处。计算机科学关注的是有限实际情况下的渐近率和工程实际值。
(*)副本是内存的原始副本。这对于int
来说没什么问题,但是复杂结构'struct'可能无法复制memmove
或者需要进一步努力。
答案 1 :(得分:0)
使用动态内存分配概念在运行时确定数组的大小:
int n;
scanf("%d",&n);
ptr = (int*) malloc(n*sizeof(int));
它将返回一个指向第一个可用内存区域的位置的指针,您可以从该位置遍历整个数组。