【问题标题】:Reallocing nested array of structs in another struct in function在函数中的另一个结构中重新分配嵌套的结构数组
【发布时间】:2021-03-10 12:04:39
【问题描述】:

我正在尝试将表(存储在文件中)存储到内存中。为了简单起见,我在这里有我编辑的代码。我遇到了分段错误,所以我认为它必须与我尝试存储值而不实际声明数组有关。但我读到它不应该是一个问题,因为结构数组本身是动态的?我真的不知道。所以在函数 addcelltoTable 我尝试了一些重新分配,但没有成功。你能帮我理解一下内存分配和指针吗?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
typedef struct Cells
{
    bool selected;
    char *Content;
} cell;

typedef struct Rows
{
    int someint;
    cell cells[];
} row;
typedef struct Tables
{
    int NumberOfColumns;
    int NumberOfRows;
    row rows[];

} table;
void addCellToTable(table *dataTable, char *cellContent, int row, int column)
{
    if (row > dataTable->NumberOfRows)
    {
        dataTable->NumberOfRows = row;
    }
    if (column > dataTable->NumberOfColumns)
    {
        dataTable->NumberOfColumns = column;
    }
    *dataTable->rows[row].cells = (cell*)realloc(dataTable->rows[row].cells, column*sizeof(char*)+1);  //here I'm trying to realloc array of cells , error: incompatible types when assigning to type ‘cell’ {aka ‘struct Cells’} from type ‘cell *’ {aka ‘struct Cells *’}
    //*dataTable->rows = (row*)realloc(dataTable->rows, (sizeof(dataTable->rows)*sizeof(char*))); //realloc array of rows ?
    *dataTable->rows[row].cells[column].Content = *cellContent;
    printf("%d : %d : %lu : %s\n", row, column, strlen(dataTable->rows[row].cells[column].Content), dataTable->rows[row].cells[column].Content);
}
int main()
{
    char numberitoa[10];
    table dataTable;
    /*dataTable.NumberOfColumns=0;
    dataTable.NumberOfRows=0;
    dataTable.rows[0].someint=0;
    dataTable.rows[0].cells[0].selected=false;
    dataTable.rows[0].cells[0].Content="";*/
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            sprintf(numberitoa, "%d", rand());
            addCellToTable(&dataTable, numberitoa, i, j);
        }
    }
    for (int i = 0; i < dataTable.NumberOfColumns + 1; i++)
    {
        for (int j = 0; j < dataTable.NumberOfRows + 1; j++)
        {
            printf("main: %d, %d, %s\n", i, j, dataTable.rows[i].cells[j].Content);
        }
        printf("\n");
    }
    return 0;
}

【问题讨论】:

  • 结构体可以包含数组,但您已将它们定义为结构体中的单元格[] 行[] 等。行为将有点依赖于标准,但您实际上并没有为它们分配任何内存。在 typedef 中提供数组大小或使用 calloc() 初始化数组元素。
  • 您是否在写入内容之前为其分配内存?
  • 将cell cells[]; 更改为cell *cells; 和rows 类似。你没有收到编译器警告吗?
  • @KamilCuk 不,没有关于结构的错误或警告。为什么更改为 *cells 才有意义?我需要存储多个单元格而不是一个。或者我可以让那个指针指向数组?
  • @ryyker 这就是我想要做的,但我真的不知道怎么做。

标签: c function struct memory-management realloc


【解决方案1】:

在结构末尾用 [] 声明的数组是一个灵活的结构数组,而不是指向数组的指针。因此,您不能重新分配它(相反,您应该重新分配整个结构)。因此,使用指向已分配内存的指针似乎更简单。这稍微改变了结构:

typedef struct Cell
{
    // You cannot use the same storage for each string as you did
    // instead we can use a fixed sized string (no allocation required)
    char Content[10]; 
    bool selected;

} cell;

typedef struct Rows
{
    int someint;
    cell * cells;
} row;
typedef struct Tables
{
    int NumberOfColumns;
    int NumberOfRows;
    row * rows;

} table;

您的分配代码中有一个微妙的问题:当您分配一行时,rows-&gt;cells 数组包含垃圾,这使得对其调用的任何函数(包括 realloc)都会崩溃。因此,这些数组必须在行分配后立即设置为 NULL。

void addCellToTable(table *dataTable, char * cellContent, int row, int column)
{ 
    if (dataTable->NumberOfRows != row + 1) {
        dataTable->rows = realloc(dataTable->rows, (row + 1) * sizeof(struct Rows));
        for (int i=0; i <= row; i++) dataTable->rows[i].cells = NULL; //<== here
    }
    if (dataTable->NumberOfColumns != column + 1)
        dataTable->rows[row].cells = realloc(dataTable->rows[row].cells, (column + 1) * sizeof(struct Cell));
    
    // The fixed sized string must be set with memcpy
    memcpy(dataTable->rows[row].cells[column].Content, cellContent, strlen(cellContent) + 1);
    
    dataTable->NumberOfRows = row + 1;
    dataTable->NumberOfColumns = column + 1;
}

最后,您的数组在每次迭代时都会重新分配,因此打印语句应该与分配在同一个循环中,否则您无法打印所有已分配的单元格。

int main()
{
    char numberitoa[10];
    table dataTable = {0};
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            sprintf(numberitoa, "%d", rand() % 1000);
            addCellToTable(&dataTable, numberitoa, i, j);

            printf("main: %d, %d, %s\n", i, j, dataTable.rows[i].cells[j].Content);
        }
    }
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-07
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    • 2021-07-15
    相关资源
    最近更新 更多