使用 realloc 和 calloc 增加函数内二维数组的大小
Increase the size of a 2D-Array inside a function with realloc and calloc
我想在一个数组中存储多个字符串(又名字符数组)。因此,我想使用二维数组。由于我不知道确切的大小(无论是单个字符串的长度还是字符串的数量),我需要动态增加大小。
为了更好的结构,我想把它放在一个单独的函数里面。但是,如果我在调整大小后访问我的数组,显然大小没有改变,并且出现分段错误。
我是 C 的新手(来自 C++ 背景)
#include<stdio.h>
#include <stdlib.h>
//I want to increase my array from [1][5] to [2][5]
void increase(char*** data)
{
*data = realloc(*data, 2 * sizeof (char*));
*data[1] = calloc(5, sizeof(char));
}
int main(void)
{
char** data = calloc(1, sizeof(char*));
data[0] = calloc(5, sizeof(char));
increase(&data);
data[1][3] = 'a'; //<-- When I access the array I get an segmentation fault
free(data);
return 0;
}
我的 char***
方法正确吗?我可以在测试环境中直接在 main 函数中实现它并且它起作用了。但是,一旦将它封装在一个函数中,我就得到了一个段。错误。
我假设这与我将数组传递给函数的方式有关,但我无法弄清楚这是什么原因以及如何解决它。有任何想法或解决方案吗?
错误(微妙的灾难性错误)在于您尝试分配传递的指针数组的第二个元素的方式,并且与 operator precedence 有关。请注意,数组下标运算符 []
比间接运算符 *
.
具有 更高的 优先级
因此,您的行:
*data[1] = calloc(5, sizeof(char));
实际上有以下作用:
*(data[1]) = calloc(5, sizeof(char));
正如您希望看到的那样,这确实不是您想要做的。
相反,您需要:
(*data)[1] = calloc(5, sizeof(char));
另一个问题(虽然不是错误,本身)是您没有对您的分配进行任何错误检查;这在使用 realloc
时尤为重要,因为按照您的代码,如果该调用失败,您将丢失 'original' 指针。最好将 realloc
中的 return 值存储在临时文件中,然后仅当该临时文件不是 NULL
.
时才覆盖原始值
这里可能会重新编写您的代码(不过,您 could/should 在 calloc
调用上添加了更多错误检查):
#include <stdio.h>
#include <stdlib.h>
int increase(char*** data)
{
char** temp = realloc(*data, 2 * sizeof(char*));
if (temp != NULL) {
*data = temp; // Only overwrite the original if we succeed!
(*data)[1] = calloc(5, sizeof(char));
return 1;
}
else {
printf("Allocation error!"); // But we still have our original "data" pointer
return 0;
}
}
int main(void)
{
char** data = calloc(1, sizeof(char*));
data[0] = calloc(5, sizeof(char));
if (increase(&data)) {
data[1][3] = 'a';
printf("%c\n", data[1][3]); // Just to do some testing!
free(data[1]); // Free the second (added) block
}
free(data[0]) // Free the first (original) block
free(data); // "data" will be valid whether or not our call to "increase" works
return 0;
}
- 您的代码仅指针数组中没有任何二维数组。你的问题是关于二维数组..
普通代码(列数不变)
void *alloc2D(const size_t rows, const size_t cols, char (*arr)[cols])
{
arr = realloc(arr, rows * sizeof(*arr));
return arr;
}
不那么琐碎的代码 - 两者都在改变。
void *alloc2D(const size_t rows, const size_t cols, const size_t oldrows, const size_t oldcols, char (*arr)[oldcols])
{
char (*newarr)[cols] = malloc(rows * sizeof(*newarr));
if(arr && newarr)
{
for(size_t r = 0; r < rows && r < oldrows; r++)
{
memcpy(newarr[r], arr[r], sizeof(*arr) > sizeof(*newarr) ? sizeof(*newarr) : sizeof(*arr));p
}
}
if(newarr) free(arr);
return newarr;
}
还有一些用法:
void *increase(const size_t oldrows, const size_t oldcols, char (*arr)[oldcols])
{
return alloc2D(oldrows+1, oldcols, arr);
}
int main(void)
{
size_t rows;
size_t cols;
if(scanf("%zu", &rows) != 1) { /* error handling*/}
if(scanf("%zu", &cols) != 1) { /* error handling*/}
char (*arr)[cols] = alloc2D(rows, cols, NULL);
char (*narr)[cols];
narr = increase(rows, cols, arr);
if(narr) arr = narr;
free(narr);
return 0;
}
我想在一个数组中存储多个字符串(又名字符数组)。因此,我想使用二维数组。由于我不知道确切的大小(无论是单个字符串的长度还是字符串的数量),我需要动态增加大小。
为了更好的结构,我想把它放在一个单独的函数里面。但是,如果我在调整大小后访问我的数组,显然大小没有改变,并且出现分段错误。
我是 C 的新手(来自 C++ 背景)
#include<stdio.h>
#include <stdlib.h>
//I want to increase my array from [1][5] to [2][5]
void increase(char*** data)
{
*data = realloc(*data, 2 * sizeof (char*));
*data[1] = calloc(5, sizeof(char));
}
int main(void)
{
char** data = calloc(1, sizeof(char*));
data[0] = calloc(5, sizeof(char));
increase(&data);
data[1][3] = 'a'; //<-- When I access the array I get an segmentation fault
free(data);
return 0;
}
我的 char***
方法正确吗?我可以在测试环境中直接在 main 函数中实现它并且它起作用了。但是,一旦将它封装在一个函数中,我就得到了一个段。错误。
我假设这与我将数组传递给函数的方式有关,但我无法弄清楚这是什么原因以及如何解决它。有任何想法或解决方案吗?
错误(微妙的灾难性错误)在于您尝试分配传递的指针数组的第二个元素的方式,并且与 operator precedence 有关。请注意,数组下标运算符 []
比间接运算符 *
.
因此,您的行:
*data[1] = calloc(5, sizeof(char));
实际上有以下作用:
*(data[1]) = calloc(5, sizeof(char));
正如您希望看到的那样,这确实不是您想要做的。
相反,您需要:
(*data)[1] = calloc(5, sizeof(char));
另一个问题(虽然不是错误,本身)是您没有对您的分配进行任何错误检查;这在使用 realloc
时尤为重要,因为按照您的代码,如果该调用失败,您将丢失 'original' 指针。最好将 realloc
中的 return 值存储在临时文件中,然后仅当该临时文件不是 NULL
.
这里可能会重新编写您的代码(不过,您 could/should 在 calloc
调用上添加了更多错误检查):
#include <stdio.h>
#include <stdlib.h>
int increase(char*** data)
{
char** temp = realloc(*data, 2 * sizeof(char*));
if (temp != NULL) {
*data = temp; // Only overwrite the original if we succeed!
(*data)[1] = calloc(5, sizeof(char));
return 1;
}
else {
printf("Allocation error!"); // But we still have our original "data" pointer
return 0;
}
}
int main(void)
{
char** data = calloc(1, sizeof(char*));
data[0] = calloc(5, sizeof(char));
if (increase(&data)) {
data[1][3] = 'a';
printf("%c\n", data[1][3]); // Just to do some testing!
free(data[1]); // Free the second (added) block
}
free(data[0]) // Free the first (original) block
free(data); // "data" will be valid whether or not our call to "increase" works
return 0;
}
- 您的代码仅指针数组中没有任何二维数组。你的问题是关于二维数组..
普通代码(列数不变)
void *alloc2D(const size_t rows, const size_t cols, char (*arr)[cols])
{
arr = realloc(arr, rows * sizeof(*arr));
return arr;
}
不那么琐碎的代码 - 两者都在改变。
void *alloc2D(const size_t rows, const size_t cols, const size_t oldrows, const size_t oldcols, char (*arr)[oldcols])
{
char (*newarr)[cols] = malloc(rows * sizeof(*newarr));
if(arr && newarr)
{
for(size_t r = 0; r < rows && r < oldrows; r++)
{
memcpy(newarr[r], arr[r], sizeof(*arr) > sizeof(*newarr) ? sizeof(*newarr) : sizeof(*arr));p
}
}
if(newarr) free(arr);
return newarr;
}
还有一些用法:
void *increase(const size_t oldrows, const size_t oldcols, char (*arr)[oldcols])
{
return alloc2D(oldrows+1, oldcols, arr);
}
int main(void)
{
size_t rows;
size_t cols;
if(scanf("%zu", &rows) != 1) { /* error handling*/}
if(scanf("%zu", &cols) != 1) { /* error handling*/}
char (*arr)[cols] = alloc2D(rows, cols, NULL);
char (*narr)[cols];
narr = increase(rows, cols, arr);
if(narr) arr = narr;
free(narr);
return 0;
}