有没有一种方法可以在C和C++之间兼容地对结构体进行零初始化?

5

问题: 我想编写一个跨C和C++兼容的代码示例。

我有一个普通的数据结构(POD),例如像这样...

typedef struct blob {
    int size;
    uint8_t * data;
} blob;

有没有一种简单的方法可以在 C 和 C++ 中都有效地进行零初始化?

如果我理解正确,在这两种语言中,以下初始化器都无效:

blob b = {0}; // valid C, invalid C++
blob b = {}; // valid C++, invalid C

到目前为止,我发现最好的是:
blob b = {0,0};

现有代码中只定义了一个结构体的部分字段,虽然目前看起来还可以,但是如果继续这样做,就会变成拼写错误。实际结构体有8个字段,这就需要注意。

问题:是否有常用惯例或跨平台的初始化方式,不需要知道结构体的所有字段?


2
memset?那是老派的方法。 - pm100
7
blob b = {0}; 是合法的 C++ 代码,但你可能会收到警告。 - HolyBlackCat
1
这是我知道的少数几个警告之一,我会关闭它。迟早我会后悔的,但到目前为止生活一直很美好。 - user4581301
2
@pm100 详细说明:memset() 不是初始化,而是赋值。 - chux - Reinstate Monica
3
我们不能再把C和C++作为同一基础语言来教授了。这两者之间有足够微妙的差别,我们不希望人们在提问时使用“C/C++”,因为对于这两种语言来说,答案总是不同的。要么教C,要么教C++。 - Martin York
显示剩余6条评论
2个回答

3

好的,宏是魔鬼孩子,但这个会有任何兴趣吗?

#ifdef __cplusplus
    #define ZERO_INIT
#else
    #define ZERO_INIT 0
#endif

...

blob b = {ZERO_INIT};

这种诡计在教程代码中使用是否有些不道德?(经评论区建议修改)

2
我会更改宏,以便代码行为:blob b = {ZERO_INIT}; - Martin York
1
@MartinYork 是的,也许这会使代码不那么晦涩。 - Paul Sanders
1
我对这个答案很满意。但是我可能建议将宏更改为像“zinit”(零初始化)这样不那么分散注意力的东西,它可以是“0”或空定义。然后代码说blob b = {zinit}; - selbie
@selbie 是的,这就是Martin建议的。回答已经编辑过了,尽管我不同意你选择的名称。宏用大写字母,对吧? - Paul Sanders
1
@Brian 我同意。你甚至不需要宏,只需执行 #ifdef __cplusplus blob b = {}; #else blob b = {0}; #endif。如果你有多个要初始化的变量,可以将它们分组在一起。 - Paul Sanders
显示剩余5条评论

2
这个声明
blob b = {0};

这段代码在C和C++中都是有效的。

如果C++编译器支持C++ 20标准,那么你也可以写成

blob b = { .size = 0, .data = 0 };

在C++中,初始化程序会生成警告,因此无法使用“-Werror”编译。| 警告:成员'blob :: data'的初始值设定项缺失[-Wmissing-field-initializers] - Zak
另外,我希望有一个构造函数,它不需要了解结构体的字段。 - Zak
3
你选择的警告设置并不是C++的问题? - Yakk - Adam Nevraumont
你说的没错,但我认为那是过于简化了。我选择启用所有警告,这样我的代码就不会被复制并生成警告了。再次强调,目标是简单明了,并为人们树立一个良好的示范。 - Zak

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