Установка n-го члена void * в структуре (и использование имени структуры против typedef) - PullRequest
0 голосов
/ 20 декабря 2018

Для игры, подобной риску, у меня есть структура для каждого региона, в каждом из которых должен быть список связанных регионов, в которые войска могут перейти из материнского региона.

Теоретически, это выглядело быкак

typedef struct {
    char* name;
    region_t* connections;
} region_t;

Однако это, конечно, невозможно из-за того, что region_t не существует до того, как синтаксический анализатор достигает типа region_t *.Поэтому я решил использовать void * вместо region_t *.

typedef struct {
    char* name;
    void* connections;
} region_t;

MiddleEast.connections = malloc(6 * sizeof(void*));
MiddleEast.connections = &SouthernEurope;
MiddleEast.(connections + 1) = &Egypt;

Используя region_t s MiddleEast, SouthernEurope и Egypt, я могу установить первое соединение на Southern Europe успешно, но когда я пытаюсь установить .(connections + 1) на &Egypt, я получаю ошибку компилятора

error: expected identifier before ‘(’ token

Как правильно получить доступ к следующему адресу памяти?

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Вы хотите создать массив пустых указателей, а не массив пустот.Вы хотите перебрать пустые указатели.

typedef struct {
    char* name;
    void **connections;
} region_t;

MiddleEast.connections = malloc(6 * sizeof(void*));
MiddleEast.connections[0] = &SouthernEurope;
MiddleEast.connections[1] = &Egypt;
free(MiddleEast.connections);

, конечно, невозможно из-за того, что region_t не существует, пока синтаксический анализатор не достигнет типа region_t *.

Вы не можете пересылать объявление typedef, но вы можете сделать это со структурой.

typedef struct region_s {
   char *name;
   struct region_s *connections;
} region_t;

Форвардное объявление часто встречается в коде C при построении связанных списков и тому подобное.sizeof(struct region_s *) известен, размер указателя struct region_s известен до определения struct region_s, поэтому вы можете:

// forward declaration
struct region_s;
// pointer is ok
struct region_s *regionpointer;
// we can define the structure after using a pointer
struct region_s {
    // you can even point to yourself
    struct region_s *regionpointer;
};
// typedef separated for readbility
typedef struct region_s region_t;

ошибка: ожидаемый идентификатор до '(' токен

MiddleEast.(connections + 1) = &Egypt;

. является оператором-членом, он получает член структуры. Строка после . берется как символ. Как вы можете видеть, тамнет элемента внутри MiddleEast структуры с именем (connections (точнее, с использованием пробела в качестве разделителя), так как такое имя запрещено. Вы хотите:

MiddleEast.connections + 1 = &Egypt;

, которая все еще не будет работать, как левая сторона= - это значение указателя внутри массива MiddleEast.connections. Вы не можете присвоить это значение; это результат добавления. (То же самое, что вы не можете int a; a + 5 = 43;). Вам нужно назначитьзначение второго элемента в массиве MiddleEast.connections равно значению &Egypt. Поэтому вам нужно отложить значение указателя.

*(MiddleEast.connections + 1) = &Egypt;

Или короче и более читабельно, так как a[b] равно*(a + b):

MiddleEast.connections[1] = &Egypt;

В шутку: пожалуйста, никогда:

1[MiddleEast.connections] = &Egypt;

MiddleEast.connections является "целым" / целым/ автономная часть, которую вы не можете отделить.

Обратите внимание, что выполнение:

MiddleEast.connections = malloc(6 * sizeof(void*));
MiddleEast.connections = &SouthernEurope;

просто приводит к утечке памяти, так как вы больше не можете free(MiddleEast.connections) освободить память.

0 голосов
/ 20 декабря 2018

Решение не void *, оно правильно использует структуры. На

структуры с именами можно ссылаться внутри себя.Тип не существует, но именованная структура существует, поэтому вы можете написать:

typedef struct region{
    char* name;
    struct region* connections;
} region_t;
...