代码:
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;
一位老师曾经告诉我"不,你不能在没有备份的情况下重新分配带有元素的数组";我说,"哦,好的",但现在这对我来说毫无意义。
指针所指向的内存已经分配,因此"不可能"丢失它;如果我做一个安全的realloc
应该没有问题。
我的问题是:如果我想调整动态数组的大小,上面的示例代码是否有效?
您的代码并不完全有效。 以下是部分注释的修改版本:
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
不为 null,则size
记录其大小。 (如果数据为空,你现在可能应该已经纾困了。 在您的原始代码中,您不知道数组的大小。 这是一个主要问题;如果您不知道数组有多大,则无法安全地使用它。
分配使用sizeof(*data)
,因此如果data
的类型发生变化(例如double *data
),malloc()
语句的其余部分不必更改。 这是不投射malloc()
或realloc()
结果的优势。
关系。再做两三件事就完美了,
- 在使用返回的指针之前检查
malloc()
是否成功。 - 如果
realloc()
失败,则不应访问具有新维度的数组。 在此代码块之后,很难确定为
,data
分配的内存是否已更改 (20) 或未更改 (10)。因此,更好的方法是检查非空- 检查 NULL 作为返回的
realloc()
指针 - 如果为 NULL,则停止/返回/中止 [如果可以,请使用旧维度进行进一步的代码]
- 否则继续使用新维度。
- 检查 NULL 作为返回的
基本上没问题。最后两行代码(用于初始化新值)需要位于 if 语句内,以防重新分配失败。否则,您将访问仅分配给 10 个元素的原始缓冲区,因此您最终将访问不属于您的内存。