Ваша структура "line" и все указатели struct просто кажутся лишними, и вы размещаете фрагментированные данные в нескольких местах, что приводит к замедлению работы кода. Попробуйте переписать всю эту вещь так:
typedef struct
{
bool isNot;
char letter;
} unit_t;
typedef struct
{
unit_t unit[3][3];
} full_data_t;
full_data_t* full_data;
full_data = malloc(sizeof *full_data);
...
free(full_data);
Если вам нужно, чтобы размеры были переменными во время выполнения, тогда C становится немного шатким. Одним из вариантов является использование элемента гибкого массива:
typedef struct
{
bool isNot;
char letter;
} unit_t;
typedef struct
{
size_t x;
size_t y;
unit_t unit[];
} full_data_t;
full_data_t* full_data;
full_data = malloc(sizeof *full_data + sizeof(unit_t[x][y]));
К сожалению, это объявляет только «искаженный» 2D-массив, поскольку unit
на самом деле является одномерным массивом (члены гибкого массива должны быть одномерными массивами). Вы можете получить к нему доступ как к двумерному массиву через указатель массива, четко определенный, не нарушая никаких правил наложения имен, но синтаксис становится немного злым:
unit_t (*unit_ptr)[y] = &full_data->unit;
...
unit_ptr[i][j]->letter = 'X';
Полный пример:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
typedef struct
{
bool isNot;
char letter;
} unit_t;
typedef struct
{
size_t x;
size_t y;
unit_t unit[];
} full_data_t;
int main(void)
{
size_t x = 3;
size_t y = 4;
full_data_t* full_data;
full_data = malloc(sizeof *full_data + sizeof(unit_t[x][y]));
unit_t (*unit_ptr)[y] = &full_data->unit;
for(size_t i=0; i<x; i++)
{
for(size_t j=0; j<y; j++)
{
unit_ptr[i][j].letter = 'A'+i*y+j; // whatever makes sense to use here
printf("%c ", unit_ptr[i][j].letter);
}
printf("\n");
}
free(full_data);
return 0;
}
Другой вариант - go с "искаженным" синтаксисом и прямой доступ к модулю full_data->, даже если это одномерный массив, с full_data->unit[i*y+j]
. Менее читабельным, на мой взгляд, но в основном вопрос стиля.