Установить указатель на массив структур, равный массиву структур - PullRequest
0 голосов
/ 19 октября 2018

У меня есть структура foo_t, в которой есть указатель на массив структуры, bar_t.У меня также есть структура spam_t, которая, с in, имеет массив struct bar_t.Моя цель - установить указатель на массив bar_t в foo_t на массив bar_t в spam_t.

Следующая программа пытается это сделать.Тогда я ожидаю, что если я изменю, например, spam->bar[2].var2, я должен увидеть новое значение, отраженное в foo.bar[2]->var2.Однако я не вижу, чтобы это произошло.Единственный случай, когда изменения в spam->bar появляются в foo.bar, это если я изменяю элемент [0].Что тут происходит?Как правильно указать foo.bar на тот же массив, что и spam->bar?

#include <stdlib.h>
#include <string.h>

typedef struct {
    uint16_t var1;
    uint16_t var2;
} bar_t ;

typedef struct {
    bar_t    (* bar)[3];
    uint8_t  spare;
} foo_t;

typedef struct {
    bar_t    bar[3];
} spam_t;


void printVar(foo_t foo, spam_t * spam)
{
    printf("foo.bar[0]->var1:  %d\n",   foo.bar[0]->var1);
    printf("foo.bar[1]->var1:  %d\n",   foo.bar[1]->var1);
    printf("foo.bar[2]->var1:  %d\n",   foo.bar[2]->var1);

    printf("spam->bar[0].var1: %d\n",   spam->bar[0].var1);
    printf("spam->bar[1].var1: %d\n",   spam->bar[1].var1);
    printf("spam->bar[2].var1: %d\n\n", spam->bar[2].var1);

    printf("foo.bar[0]->var2:  %d\n",   foo.bar[0]->var2);
    printf("foo.bar[1]->var2:  %d\n",   foo.bar[1]->var2);
    printf("foo.bar[2]->var2:  %d\n",   foo.bar[2]->var2);

    printf("spam->bar[0].var2: %d\n",   spam->bar[0].var2);
    printf("spam->bar[1].var2: %d\n",   spam->bar[1].var2);
    printf("spam->bar[2].var2: %d\n\n", spam->bar[2].var2);
}

int main(int argc, char * argv[])
{
    printf("Start...\n");

    foo_t    foo;
    spam_t * spam = (spam_t *)malloc(sizeof(spam_t));

    memset(&foo, 0, sizeof(foo_t));
    memset(spam, 0, sizeof(spam_t));

    foo.bar = &(spam->bar);

    printVar(foo, spam);

    spam->bar[0].var1 = 1;
    spam->bar[1].var1 = 1;
    spam->bar[2].var1 = 0;

    spam->bar[0].var2 = 2;
    spam->bar[1].var2 = 1;
    spam->bar[2].var2 = 0;

    //foo.bar[2]->var2 = 3;

    printVar(foo, spam);

    free(spam);

    printf("Done...\n");

    return 0;
}

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

Проблема в том, что foo.bar - это указатель на массив bar_t размера 3. Поэтому, когда вы используете foo.bar [1], вы выйдете за пределы этого массива.

Один из возможных способов обойти это - использовать массив размером 1:

typedef struct {
    bar_t    (* bar)[1];
    uint8_t  spare;
} foo_t;

Это вызовет предупреждение о несовместимом типе указателя, что и должно быть.Но это работает так, как вы хотите.

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

0 голосов
/ 19 октября 2018

Вы правильно назначаете адрес массива указателю, но я думаю, что способ доступа к вашим элементам неверен.

Вам следует изменить

foo.bar[0]->var1

на

(*foo.bar)[0].var1

foo.bar[0]->var1 эквивалентно (*foo.bar[0]).var1.Но поскольку foo.bar является указателем на массив, вы хотите сначала разыменовать указатель, а затем применить подписку на массив.Поэтому вы должны написать (*foo.bar)[0].var1.

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