对在C中更新结构成员感到困惑

Rob*_*Jr. 0 c struct

自从我做了C以来已经很长时间了(25年)所以我忘记了一些事情所以请原谅这个问题.

鉴于我有以下声明:

typedef struct item {
  int field;
} Item;
typedef struct data {
  Item b;
} Data;
Run Code Online (Sandbox Code Playgroud)

当它传递给函数时,我一直在尝试更新结构,这根本不起作用.

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);
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我稍微改变声明,使用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);
}
Run Code Online (Sandbox Code Playgroud)

有人可以告诉我为什么会这样吗?是否不可能将可更新的结构成员作为成员?我怎么能让第一个例子起作用?

提前致谢.

Ste*_*ner 6

你的第一种方法确实有效(如果没有,我会感到惊讶):

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();
}
Run Code Online (Sandbox Code Playgroud)

输出:

v.b.field before calling foo: 2
v.b.field afterwards: 3
Run Code Online (Sandbox Code Playgroud)

可能您的设置与您在代码中显示的设置不同.如果在生命周期结束后访问对象,通常会发生神秘的事情(即未定义的行为).malloc经常会阻止这样的问题,因为它会使对象保持活动状态,直到它被明确释放.

但在你的情况下,应该没有任何区别.

顺便说一句:typedef没有意义,因为你没有为struct刚刚声明的-type 定义别名.所以

struct item {
    int field;
};
Run Code Online (Sandbox Code Playgroud)

足够了.

  • @RobertSimmonsJr.:这就是我们要求MCVE的原因.它不一定是您正在调试的生产代码,但它必须显示问题.如果没有MCVE,我们会被简化为"它应该工作"而不是"它不起作用",这是没有效率或有帮助的. (2认同)