在C语言中初始化一个结构体

5

我是一个有用的助手,可以为您翻译文本。以下是需要翻译的内容:

我对C语言中的结构初始化有一个问题。我有一个结构体:

struct TestStruct
{
u8 status;
u8 flag1;
u8 flag2;
};

我希望有一个通用的函数/宏来初始化这个结构体并设置一个参数的值,例如 status = 1,简单的方法是:
TestStruct t = {};
t.status = 1;

然而,通过这样做,我已经两次设置了状态值,首先在init函数中将其设置为0,然后第二次将其设置为1(优化没有帮助?)。 (请不要告诉我t = {1,0,0},我正在寻找一种通用的方法) 我在考虑在init函数中使用宏,例如:
#define INIT_TESTSTRUCT (param, value) \
{ .status=0, .flag1=0, .flag2=0, .param=value }
TestStruct t = INIT_TESTSTRUCT(status, 0);

然而,编译器会报错“initialized field overwritten”,因为我设置了status的值两次。
请帮忙指出如何修改宏以达到我想要的效果,非常感谢。
3个回答

6
#define INIT_TESTSTRUCT(param, value) \
    { .param=(value) }
TestStruct t = INIT_TESTSTRUCT(status, 0);

应该这样做。变量然后添加在.data段中 - 因为它是一个初始化的变量 - 所有未明确指定的字段都由编译器设置为0(而不是链接器或加载器)。


谢谢,这帮助我理解结构体初始化函数 :) - Maluvel
值不应该在()括号中吗?我不确定缺少它们是否会导致任何问题,但是保险起见总是好的。 - Darth Hunterix
你是对的,value 应该在它周围加上 (),以防它包含混淆的内容,但在 param 的情况下,这样做会适得其反。 - glglgl
通常情况下,如果您有一个可以放入函数中的宏,您会使用 ()#define TWICE(x) (2*(x))。在这种情况下,TWICE(2 + 2) 产生 (2*(2+2)) ,这是可以接受的。但仅有 2*x 的话,您可以使用 ~TWICE(2+2),这将得到 ~2*2+2,而这更可能意味着 ((~2)*2)+2,而非预期结果。 - glglgl

2
你的空格放错位置了:
#define INIT_TESTSTRUCT(param, value) \
{ .status=0, .flag1=0, .flag2=0, .param=(value) }

应该这样做。

宏定义中的(必须紧接着宏名称。否则,解析器将其视为没有参数的宏并将其扩展为(param, value) ...等等...。在您的情况下,这显然是语法错误。

此外,请注意,在替换文本中加上()通常是一个好主意,以避免语法混淆。


1
首先,首先

TestStruct t = {};

在C语言中,这是非法的。如果它在您的情况下编译通过了,那么它必须是一个非标准的编译器扩展。您可以通过使用...来达到相同的效果。
TestStruct t = { 0 };

这在C语言中是合法的。它将结构体中所有字段都设置为零。

其次,即使使用指定的初始化程序,C语言仍然遵循传统的“全有或全无”初始化方法:如果只初始化聚合体的一个字段,则所有其他字段都会隐式地初始化为零。

这意味着在您的情况下,您只需要做到以下这点:

TestStruct t = { .status = 1 };

初始化整个结构体。 status 字段将被设置为 1,而所有其他字段将被设置为零。

因此,您的宏可以实现为

#define INIT_TESTSTRUCT(param, value) { .param = value }
TestStruct t = INIT_TESTSTRUCT(status, 1);

不需要显式将所有其他字段设置为零 - 它会自动发生。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接