Запутался в обновлении члена структуры в C - PullRequest
0 голосов
/ 06 мая 2018

Это было ДОЛГОЕ время (25 лет) с тех пор, как я сделал C, и поэтому я забываю некоторые вещи, поэтому, пожалуйста, прости вопрос.

Учитывая, что у меня есть следующие объявления:

typedef struct item {
  int field;
} Item;
typedef struct data {
  Item b;
} Data;

Я пытался обновить структуру, когда она передается функции, и это не работает вообще.

static void foo(Data *data) {
  data->b.field = 3; // doesn't work, the struct remains unchanged.
}
static void test() {
  Data v = {.b = {.field = 2}};
  foo(&v);
}

Однако, если я немного изменил объявление, используйте malloc для его выделения.

typedef struct data {
  Item *b;
};
static void foo(struct data *data) {
  data->b->field = 3; // works.
}
static void test() {
  Data v = (struct data*) malloc(sizeof(Data));
  Item i = (struct item*) malloc(sizeof(Item));
  foo(v);
  free(i);
  free(v);
}

Может кто-нибудь сообщить мне, почему это так?Разве невозможно иметь члены структуры, которые можно обновлять как члены?Как я мог заставить работать первый пример?

Заранее спасибо.

1 Ответ

0 голосов
/ 06 мая 2018

Ваш первый подход действительно работает (и я был бы удивлен, если бы он этого не сделал):

struct item {
    int field;
};

struct data {
    struct item b;
};

static void foo(struct data *data) {
    data->b.field = 3;
}
static void test() {
    struct data v = {.b = {.field = 2}};
    printf("v.b.field before calling foo: %d\n", v.b.field);
    foo(&v);
    printf("v.b.field afterwards: %d\n", v.b.field);
}

int main() {
    test();
}

Выход:

v.b.field before calling foo: 2
v.b.field afterwards: 3

Возможно, ваши настройки отличаются от тех, которые вы указали в коде. Таинственные вещи (то есть неопределенное поведение) часто случаются, если вы обращаетесь к объекту после того, как закончилось его время жизни. malloc часто предотвращает такие проблемы, поскольку поддерживает объект живым, пока он не будет явно освобожден

Но в вашем случае не должно быть никакой разницы.

Кстати: typedef не имеет смысла, так как вы не определяете псевдоним для только что объявленного struct -типа. Итак

struct item {
    int field;
};

достаточно.

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