什么是正确的方式来初始化一个非常大的结构?

在我们的代码中,我们曾经有过这样的东西:

   *(controller->bigstruct) = ( struct bigstruct ){ 0 };

这曾经效果很好,然后我们升级了GCC版本,并突然开始看到堆栈溢出。 看着程序集,旧的GCC代码(2.x)基本上是这样做的:

memset(controller->bigstruct, 0, sizeof(struct bigstruct));

新的GCC(3.4.x)正在这样做

   struct bigstruct temp = { 0 };
   controller->bigstruct = temp;

在回顾了C99规范后,我可以明白为什么; C99基本上要求在栈上存在匿名结构。 这是一个很好的概念,但是这个结构是4兆字节大,并且只是有意存在于堆上!

我们采取了自己的'初始化'功能来明确设置成员,但这很丑陋,也是一个令人头痛的问题。 我不认为memset是一个适当的解决方案,因为我不知道0的位值是否为该类型的适当的零值(我知道,nit-picking,但是在那里;我不介意编译器会这样做,因为它可以知道)

什么是“正确的”,或者至少是最好的方法来初始化这样的大型结构?

为了进一步澄清为什么我认为memset不是解决方案:未初始化的成员的初始化规则与静态初始化相同,如下所示: - 如果它有指针类型,则将其初始化为空指针; - 如果它有算术类型,则它被初始化为(正或无符号)零; ...

'memset'会将内存设置为位模式零,这不一定是相同的事情。 设想一个不使用IEEE浮点数的系统。 不寻常的,但由C支持。0.0的表示并不一定意味着“全位零”,它可以是处理器的任何方便。


memset是要走的路。 你没有很多选择。

做类似的事情:

#define InitStruct(var, type) type var; memset(&var, 0, sizeof(type))

所以你只需要:

InitStruct(st, BigStruct);

然后像往常一样使用...

我不明白“0”是不是结构的有效“0”类型。 “批量初始化”结构的唯一方法是将其所有内存设置为一个值; 否则你将不得不做出额外的逻辑来告诉它使用每个成员的特定位模式。 使用的最佳“通用”位模式是0。

此外 - 这与您在使用时使用的逻辑相同

*(controller->bigstruct) = *( struct bigstruct ){ 0 };

因此,我不会让你不愿意使用它:)

对这篇文章的第一评论让我在打电话给他和白痴​​之前做了一些研究,然后我发现了这一点:

http://www.lysator.liu.se/c/c-faq/c-1.html

很有意思; 如果我可以投票评论我会:)

这就是说 - 你唯一的选择,如果你想针对具有非零空值的古老体系结构仍然是手动初始化某些成员。

感谢Thomas Padron-McCarthy! 我今天学了些新东西 :)


如果你不想使用memset,你总是可以声明你的结构的静态副本并使用memcpy,这会得到类似的性能。 这会为你的程序增加4 megs,但可能比设置单个元素更好。

也就是说,如果GCC使用的是memset,而且之前已经足够好了,那么现在我认为它已经足够好了。


正如其他人所说,memset是要走的路。 但是,不要在C ++对象上使用memset,尤其是那些使用虚拟方法的对象。 sizeof( foo )将包含虚拟函数指针表,并且对其执行memset会导致严重的悲伤。

如果memset本身没有解决问题,只需执行一个memset,然后初始化任何非零的成员(即非IEEE浮点值)。

链接地址: http://www.djcxy.com/p/73573.html

上一篇: What is the correct way to initialize a very large struct?

下一篇: Static assert in C