Как выделить память и заполнить структуру указателем на двумерный массив - PullRequest
0 голосов
/ 15 февраля 2019

Мне нужно выделить достаточно памяти для структуры с указателем на двумерный массив символов.И затем заполните структуру

struct Dataset
{
    int size;
    char (*items)[][MAX_STRING_LENGTH];
};

Я попытался выделить память только для структуры и двумерного массива следующим образом

struct Dataset * dataset = malloc( sizeof (Dataset) + (2 * sizeof(char[2][15])) )

И затем заполнить двумерный массив следующим образом, но я 'я не в состоянии сделать это

strcpy((*dataset->items)[0][0], "HELLO WORLD");

Ответы [ 3 ]

0 голосов
/ 15 февраля 2019

Есть как минимум два способа сделать это.Одним из них является способ, изложенный в вопросе, с указателем на двумерный массив 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;
}

Выходные данные этого кода совпадают с выходными данными издругой код.

0 голосов
/ 17 февраля 2019

Я нашел свои ошибки две ошибки.

Первая.
Я должен инициализировать первый размер массива на ноль, чтобы позже изменить его размер с помощью malloc, например,

struct Dataset
{
    int size;
    char (*items)[0][MAX_STRING_LENGTH];
};

Второй
Чтобы изменить значение массива в позиции Iне может пользователь (*dataset->items)[x][y].Я должен удалить *

strcpy((dataset->items)[0][0], "HELLO WORLD");
0 голосов
/ 15 февраля 2019

Позволяет понять, что такое char (*items)[][MAX_STRING_LENGTH];.

Это указатель на массив массива символов MAX_STRING_LENGTH .

Таким образом, item потребуется 4 или 8 байт в зависимости от вашей платформы.

Все, что вы размещаете здесь после знака +, является пустой тратой:

struct Dataset * dataset = malloc( sizeof (Dataset) **+** (2 * sizeof(char[2][15])) )

Измените это на:

struct Dataset * dataset = malloc( sizeof ( struct Dataset));

Теперь вам нужен указатель item, указывающий куда-то направо,

Так что выделите память и точкук нему:

dataset->item = malloc(sizeof(char[2][MAX_STRING_LENGTH]));

Теперь у вас есть item, указывающий на действительную память. Используйте это.

// ------------------------------------------------------------

Не ответ. Я твердо верю, что само объявление вашей структуры ошибочно.Если вы могли бы опубликовать желание достичь, то это будет полезно.

...