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

对在C中更新结构成员感到困惑,c,struct,C,Struct,我已经有很长一段时间(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 remai

我已经有很长一段时间(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);
}
有人能告诉我这是为什么吗?不可能有可更新为成员的结构成员吗?我如何才能使第一个示例起作用


提前感谢。

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

输出:

v.b.field before calling foo: 2
v.b.field afterwards: 3
您的设置可能与代码中显示的设置不同。如果在对象的生命周期结束后访问该对象,则通常会发生神秘的事情(即未定义的行为)<代码>malloc通常会防止此类问题,因为它会使对象保持活动状态,直到显式释放为止

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


顺便说一句:
typedef
没有意义,因为您没有为刚刚声明的
struct
-类型定义别名。所以

struct item {
    int field;
};

已经足够了。

您的第一种方法实际上是有效的(如果它不起作用,我会感到惊讶):

输出:

v.b.field before calling foo: 2
v.b.field afterwards: 3
您的设置可能与代码中显示的设置不同。如果在对象的生命周期结束后访问该对象,则通常会发生神秘的事情(即未定义的行为)<代码>malloc通常会防止此类问题,因为它会使对象保持活动状态,直到显式释放为止

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


顺便说一句:
typedef
没有意义,因为您没有为刚刚声明的
struct
-类型定义别名。所以

struct item {
    int field;
};

足够了。

typedef
如果没有声明符就没有意义。你的编译器没有对此抱怨吗?你需要创建一个。是的,它应该编译,至少在旧规则下(C90)。不,这是不明智的。讨论的这一部分有一个重复,但它与问题的主旨相切。
typedef
如果没有声明符就没有意义。你的编译器没有对此抱怨吗?你需要创建一个。是的,它应该编译,至少在旧规则下(C90)。不,这是不明智的。这部分的讨论有重复,但它与问题的主旨相切。是的,我知道别名,只是没有写它。我很冷。实际代码是专有的。至于这个问题。我确信它在我之后放入printf时不起作用,它是旧的值。@robertsinmonsjr.:这就是我们请求MCVE的原因。它不一定是您正在调试的生产代码,但它必须显示问题所在。如果没有MCVE,我们只能说“它应该工作”而不是“它不工作”,这既没有效率也没有帮助。那么我一定是做错了什么。我会调查的。谢谢你的帮助。是的,我知道别名,只是没写。我很冷。实际代码是专有的。至于这个问题。我确信它在我之后放入printf时不起作用,它是旧的值。@robertsinmonsjr.:这就是我们请求MCVE的原因。它不一定是您正在调试的生产代码,但它必须显示问题所在。如果没有MCVE,我们只能说“它应该工作”而不是“它不工作”,这既没有效率也没有帮助。那么我一定是做错了什么。我会调查的。谢谢你的帮助。