重新分配 C 数组以获得更多 space
Re allocating C array for more space
我正在编写一个带有函数 add(a , i, n) 的程序,它将 'i' 作为一个元素添加到 'a',但是如果数组 'a' 用完了space,那么我需要为数组重新分配更多内存。我被困在这里:
#include <stdlib.h>
#include <stdio.h>
int add(int* a, int i, int n);
int main(){
int n = 20;
int *a = (int*) malloc(n*sizeof(int));
int i;
for (i = 0; i < 100000; i++){
n = add(a, i, n);
printf("a[%d]=%d\n",i,(int)a[i]);
}
return 0;
}
int add(int *a, int i, int n){
if (i >= n){
n++;
int* b = (int*) realloc(a, n*sizeof(int));
a[i]=i;
return n;
}else{
}
}
我不是很有经验,所以请温柔...
要在 C
中有一个自动增长的数组,您通常需要一个辅助函数 ensure_capacity
来处理数组重新分配。
辅助函数最好使用 2x 增长策略进行重新分配,这样您就有了 append 操作的摊销常数时间。
代码看起来有点像下面。
请注意,代码使用数组的前 2 个元素来保留其 capacity/size。您可以使用 struct
的指针 + 大小来代替,但是您需要使两者彼此靠近,否则代码将不容易阅读。
int* ensure_capacity(int* vec, int new_cap) {
if (vec == 0) {
vec = (int*) malloc(18 * sizeof(int));
vec [0] = 16;
vec [1] = 0;
} else {
int cap = vec[0];
if (cap < new_cap) {
do {
cap *= 2;
} while (cap < new_sz);
int* new_vec = (int*) realloc(vec, cap * sizeof(int));
if (new_vec != null) {
vec = new_vec;
vec[0] = cap;
} else {
// reallocation failed, handle the error
}
}
}
return vec;
}
您可以在 add()
函数中使用它,例如:
int* push_back(int* vec, int val) {
vec = ensure_capacity(vec, vec[1] + 1);
vec[vec[1]++] = val;
return vec;
}
realloc
尝试重新分配给定的内存,但有时,它不能并给你一个新的内存指针。
必须像这样使用:
int *b;
b = realloc(a, <newsize>);
if (b) {
/* realloc succeded, `a` must no longer be used */
a = b;
/* now a can be used */
printf("ok\n");
} else {
/* realloc failed, `a` is still available, but it's size did not changed */
perror("realloc");
}
现在,您的代码仍有一些问题:
函数add()
的思路是在需要的时候重新分配a
,但是a
是copy给的,所以在main
中它的值不会改变.
#include <stdlib.h>
#include <stdio.h>
int add(int** a, int i, int n);
int main(){
int n = 20;
int *a = malloc(n*sizeof(int));
int i;
for (i = 0; i < 100000; i++) {
/* note how `a` is passed to `add` */
n = add(&a, i, n);
printf("a[%d]=%d\n",i,a[i]);
}
/* and finally free `a`*/
free(a);
return 0;
}
/* changed `a` type to make its new value visible in `main` */
int add(int **a, int i, int n){
if (i >= n){
/* want to write a[i], so size must be at least i+1*/
n = i+1;
/* realloc memory */
int *b = realloc(*a, n*sizeof(int));
/* check that `realloc` succeded */
if (!b) {
/* it failed!*/
perror("realloc");
exit(1);
}
/* store new memory address */
*a = b;
}
/* update memory */
(*a)[i]=i;
/* return new size */
return n;
}
注意:我删除了 malloc
/realloc
转换,请参阅:Do I cast the result of malloc?
我正在编写一个带有函数 add(a , i, n) 的程序,它将 'i' 作为一个元素添加到 'a',但是如果数组 'a' 用完了space,那么我需要为数组重新分配更多内存。我被困在这里:
#include <stdlib.h>
#include <stdio.h>
int add(int* a, int i, int n);
int main(){
int n = 20;
int *a = (int*) malloc(n*sizeof(int));
int i;
for (i = 0; i < 100000; i++){
n = add(a, i, n);
printf("a[%d]=%d\n",i,(int)a[i]);
}
return 0;
}
int add(int *a, int i, int n){
if (i >= n){
n++;
int* b = (int*) realloc(a, n*sizeof(int));
a[i]=i;
return n;
}else{
}
}
我不是很有经验,所以请温柔...
要在 C
中有一个自动增长的数组,您通常需要一个辅助函数 ensure_capacity
来处理数组重新分配。
辅助函数最好使用 2x 增长策略进行重新分配,这样您就有了 append 操作的摊销常数时间。
代码看起来有点像下面。
请注意,代码使用数组的前 2 个元素来保留其 capacity/size。您可以使用 struct
的指针 + 大小来代替,但是您需要使两者彼此靠近,否则代码将不容易阅读。
int* ensure_capacity(int* vec, int new_cap) {
if (vec == 0) {
vec = (int*) malloc(18 * sizeof(int));
vec [0] = 16;
vec [1] = 0;
} else {
int cap = vec[0];
if (cap < new_cap) {
do {
cap *= 2;
} while (cap < new_sz);
int* new_vec = (int*) realloc(vec, cap * sizeof(int));
if (new_vec != null) {
vec = new_vec;
vec[0] = cap;
} else {
// reallocation failed, handle the error
}
}
}
return vec;
}
您可以在 add()
函数中使用它,例如:
int* push_back(int* vec, int val) {
vec = ensure_capacity(vec, vec[1] + 1);
vec[vec[1]++] = val;
return vec;
}
realloc
尝试重新分配给定的内存,但有时,它不能并给你一个新的内存指针。
必须像这样使用:
int *b;
b = realloc(a, <newsize>);
if (b) {
/* realloc succeded, `a` must no longer be used */
a = b;
/* now a can be used */
printf("ok\n");
} else {
/* realloc failed, `a` is still available, but it's size did not changed */
perror("realloc");
}
现在,您的代码仍有一些问题:
函数add()
的思路是在需要的时候重新分配a
,但是a
是copy给的,所以在main
中它的值不会改变.
#include <stdlib.h>
#include <stdio.h>
int add(int** a, int i, int n);
int main(){
int n = 20;
int *a = malloc(n*sizeof(int));
int i;
for (i = 0; i < 100000; i++) {
/* note how `a` is passed to `add` */
n = add(&a, i, n);
printf("a[%d]=%d\n",i,a[i]);
}
/* and finally free `a`*/
free(a);
return 0;
}
/* changed `a` type to make its new value visible in `main` */
int add(int **a, int i, int n){
if (i >= n){
/* want to write a[i], so size must be at least i+1*/
n = i+1;
/* realloc memory */
int *b = realloc(*a, n*sizeof(int));
/* check that `realloc` succeded */
if (!b) {
/* it failed!*/
perror("realloc");
exit(1);
}
/* store new memory address */
*a = b;
}
/* update memory */
(*a)[i]=i;
/* return new size */
return n;
}
注意:我删除了 malloc
/realloc
转换,请参阅:Do I cast the result of malloc?