重新分配一个数组但不要丢失其中的元素
Realloc an array but do not lose the elements in it
代码:
int * data;
data = malloc(sizeof(int)*10);
int i;
for(i=0;i<10;i++)
data[i]=i;
int * aux;
aux = realloc(data,sizeof(int)*20);
if(aux)
data=aux;
for(i=10;i<20;i++)
data[i]=i;
曾经有位老师告诉我"No, you can't reallocate an array with elements without a backup";我说,"Oh, OK",但现在这对我来说毫无意义。
指针指向的内存已经分配,所以"impossible"失去它;如果我做一个保险箱 realloc
应该没有问题。
我的问题是:如果我想调整动态数组的大小,上面的示例代码是否有效?
基本上没问题。初始化新值的最后两行代码需要位于 if 语句中,以防重新分配失败。否则你正在访问你的原始缓冲区,它只分配给 10 个元素,所以你最终会访问不属于你的内存。
没关系。只是 两个 三件事让它变得完美,
- 在使用返回的指针之前检查
malloc()
是否成功。
- 如果
realloc()
失败,您不应访问具有新维度的数组。
在这个代码块之后,很难找出为data
分配的内存是否已更改(20)或未更改(10)。因此,更好的方法是不检查非 NULL,
- 检查 NULL 作为
realloc()
的返回指针
- stop/return/abort 如果它为 NULL [或者使用旧维度作为进一步的代码,如果可以的话]
- 否则继续新维度。
您的代码不完全有效。这是部分注释的修改版本:
size_t size = 10; // Keep a record of the size of the array
int *data = malloc(sizeof(*data) * size);
if (data != 0) // Always check that the allocation succeeds
{
for (size_t i = 0; i < size; i++)
data[i] = i;
size_t new_size = size * 2; // Grow arrays by doubling as a general rule
int *aux = realloc(data, sizeof(*aux) * new_size);
if (aux != 0) // Test allocation - as you did anyway
{
data = aux;
// Only initialize new data if successful
for (size_t i = size; i < new_size; i++)
data[i] = i;
size = new_size; // Record new size of array
}
}
/* At this point, if data != 0, it is safe to access data[0]..data[size-1] */
您需要知道此片段末尾的数组有多大。在此版本中,如果 data
不为空,则 size
记录其大小。 (如果数据为空,您现在可能应该退出。)在您的原始代码中,您不知道数组的大小。这是一个主要问题;如果你不知道它有多大,你就不能安全地使用它。
分配使用sizeof(*data)
,这样如果data
的类型改变(比如double *data
),malloc()
语句的其余部分不必改变.这是不转换 malloc()
或 realloc()
.
结果的优势
代码:
int * data;
data = malloc(sizeof(int)*10);
int i;
for(i=0;i<10;i++)
data[i]=i;
int * aux;
aux = realloc(data,sizeof(int)*20);
if(aux)
data=aux;
for(i=10;i<20;i++)
data[i]=i;
曾经有位老师告诉我"No, you can't reallocate an array with elements without a backup";我说,"Oh, OK",但现在这对我来说毫无意义。
指针指向的内存已经分配,所以"impossible"失去它;如果我做一个保险箱 realloc
应该没有问题。
我的问题是:如果我想调整动态数组的大小,上面的示例代码是否有效?
基本上没问题。初始化新值的最后两行代码需要位于 if 语句中,以防重新分配失败。否则你正在访问你的原始缓冲区,它只分配给 10 个元素,所以你最终会访问不属于你的内存。
没关系。只是 两个 三件事让它变得完美,
- 在使用返回的指针之前检查
malloc()
是否成功。 - 如果
realloc()
失败,您不应访问具有新维度的数组。 在这个代码块之后,很难找出为
data
分配的内存是否已更改(20)或未更改(10)。因此,更好的方法是不检查非 NULL,- 检查 NULL 作为
realloc()
的返回指针
- stop/return/abort 如果它为 NULL [或者使用旧维度作为进一步的代码,如果可以的话]
- 否则继续新维度。
- 检查 NULL 作为
您的代码不完全有效。这是部分注释的修改版本:
size_t size = 10; // Keep a record of the size of the array
int *data = malloc(sizeof(*data) * size);
if (data != 0) // Always check that the allocation succeeds
{
for (size_t i = 0; i < size; i++)
data[i] = i;
size_t new_size = size * 2; // Grow arrays by doubling as a general rule
int *aux = realloc(data, sizeof(*aux) * new_size);
if (aux != 0) // Test allocation - as you did anyway
{
data = aux;
// Only initialize new data if successful
for (size_t i = size; i < new_size; i++)
data[i] = i;
size = new_size; // Record new size of array
}
}
/* At this point, if data != 0, it is safe to access data[0]..data[size-1] */
您需要知道此片段末尾的数组有多大。在此版本中,如果 data
不为空,则 size
记录其大小。 (如果数据为空,您现在可能应该退出。)在您的原始代码中,您不知道数组的大小。这是一个主要问题;如果你不知道它有多大,你就不能安全地使用它。
分配使用sizeof(*data)
,这样如果data
的类型改变(比如double *data
),malloc()
语句的其余部分不必改变.这是不转换 malloc()
或 realloc()
.