Есть как минимум два способа сделать это.Одним из них является способ, изложенный в вопросе, с указателем на двумерный массив char
.Другой использует гибкий элемент массива (FAM).
Указатель на двумерный массив
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAX_STRING_LENGTH = 15 };
struct Dataset
{
int size;
char (*items)[][MAX_STRING_LENGTH];
};
int main(void)
{
int rows = 3;
struct Dataset *dataset = malloc(sizeof(struct Dataset) + (sizeof(char[rows][MAX_STRING_LENGTH])));
dataset->size = rows;
dataset->items = (void *)((char *)dataset + sizeof(struct Dataset));
for (int i = 0; i < rows; i++)
sprintf((*dataset->items)[i], "Row 0x%.*X", 2*(i+2), i);
for (int i = 0; i < rows; i++)
printf("Row %d: [%s]\n", i+1, (*dataset->items)[i]);
free(dataset);
return 0;
}
Это выделяет достаточно места для структуры и двумерного массива.Первый ключевой шаг, не показанный в вопросе, - это обеспечение инициализации элемента items
;он должен указывать куда-то, и вы выделяете пространство после структуры для массива.Второй ключевой шаг - правильно использовать указатель на 2D-массив.Обратите внимание, что нет никаких сложностей с выравниванием для двумерного массива символов.Если бы это был 2D-массив некоторых других типов, вам, возможно, придется беспокоиться о выравнивании, хотя есть вероятность, что структура будет иметь правильный размер, так что выравнивание не является проблемой (если, возможно, вы не используете компилятор с 32-разрядными адресамии int
и 16-байтовые long double
и long double
должны быть выровнены по 16-байтовой границе - я не уверен, что такой компилятор существует).
Вывод:
Row 1: [Row 0x0000]
Row 2: [Row 0x000001]
Row 3: [Row 0x00000002]
Элемент гибкого массива
При этом массив с пустым начальным измерением используется в качестве последнего элемента структуры с хотя бы одним другим элементом.На этот раз нет необходимости вычислять смещение и не нужно использовать специальные обозначения для доступа к элементам массива:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAX_STRING_LENGTH = 15 };
struct Dataset
{
int size;
char items[][MAX_STRING_LENGTH];
};
int main(void)
{
int rows = 3;
struct Dataset *dataset = malloc(sizeof(struct Dataset) + (sizeof(char[rows][MAX_STRING_LENGTH])));
dataset->size = rows;
for (int i = 0; i < rows; i++)
sprintf(dataset->items[i], "Row 0x%.*X", 2*(i+2), i);
for (int i = 0; i < rows; i++)
printf("Row %d: [%s]\n", i+1, dataset->items[i]);
free(dataset);
return 0;
}
Выходные данные этого кода совпадают с выходными данными издругой код.