我想在一個陣列中存盤多個字串(又名字符陣列)。因此,我想使用二維陣列。由于我不知道確切的大小(無論是單個字串的長度還是字串的數量),我需要動態增加大小。
為了更好的結構,我想把它放在一個單獨的函式中。但是,如果我在調整陣列大小后訪問它,顯然大小沒有改變,并且出現分段錯誤。
我是 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 函式中實作它并且它起作用了。但是,一旦將它封裝在一個函式中,我就得到了一個 seg。過錯。
我認為這與我將陣列傳遞給函式的方式有關,但我無法弄清楚這是什么原因以及如何解決它。有沒有人有一些想法或解決方案?
uj5u.com熱心網友回復:
- 您的代碼中沒有任何二維陣列,只有指標陣列。你的問題是關于二維陣列..
瑣碎代碼(列數不變)
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;
}
uj5u.com熱心網友回復:
錯誤(這是微妙的災難性)在于您嘗試分配傳遞的指標陣列的第二個元素的方式,并且與operator precedence相關。請注意,陣列下標操作,[]具有較高的比間接運算子優先級*。
因此,您的線路:
*data[1] = calloc(5, sizeof(char));
實際上有以下作用:
*(data[1]) = calloc(5, sizeof(char));
正如您所希望的那樣,這真的不是您想要做的。
相反,您需要:
(*data)[1] = calloc(5, sizeof(char));
另一個問題(盡管本身不是錯誤)是您沒有對分配進行任何錯誤檢查;這在使用時尤其重要,realloc因為就您的代碼而言,如果該呼叫失敗,您將丟失“原始”指標。最好將回傳值存盤realloc在臨時檔案中,然后僅當該臨時檔案不是時才覆寫原始值NULL。
這是您的代碼可能的重新作業(不過,您可以/應該對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;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/358028.html
上一篇:函式內部的基本函式
