当前位置:  开发笔记 > 前端 > 正文

初始化非常大的结构的正确方法是什么?

如何解决《初始化非常大的结构的正确方法是什么?》经验,为你挑选了2个好方法。

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

   *(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的位值是该类型的适当零值(我知道,但是你知道,但是你有;我不介意编译器做到了,因为它可以知道)

初始化像这样的大型结构的"正确"或至少是最好的方法是什么?

为了进一步阐明我认为memset不是解决方案的原因:未明确初始化的成员的初始化规则与静态初始化相同,如下: - 如果它有指针类型,则初始化为空指针; - 如果它有算术类型,则初始化为(正或无符号)零; ...

'memset'会将内存设置为位模式为零,这不一定是一回事.想象一下不使用IEEE浮点数的系统.不寻常,但由C支持.0.0的表示不一定意味着"全位零",它可以是处理器方便的任何东西.



1> 小智..:

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

做类似的事情:

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

所以你只需要:

InitStruct(st, BigStruct);

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

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

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

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

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

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

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

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

话虽这么说 - 如果你想要使用非0空值来定位古老的架构,你唯一的选择仍然是对某些成员进行手动初始化.

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


源代码中的{0}不一定转换为全零位模式.例如,指针上下文中的源代码中的0将被解释为NULL指针,但是NULL指针不需要表示为全零位.
@dmckee:通过将声明包装在新范围内,难道不会破坏实际声明新变量的目的吗?

2> SmacL..:

如果您不想使用memset,您可以随时声明结构的静态副本并使用memcpy,这将提供类似的性能.这将为您的程序添加4兆,但可能比设置单个元素更好.

也就是说,如果GCC使用的是memset,之前它已经足够好了,我建议它现在已经足够好了.


由于`{0}`结构本质上是一个零字节序列(除非你在一些非常疯狂的平台上),这不会给程序增加4M.零初始化的全局对象转到不同的部分,而不是放在程序映像中 - 如果整个部分全为零,那么它的意义何在?此外,这个静态结构甚至不会在运行时使用任何内存,因为操作系统的VM子系统将整个内存范围映射到具有写时复制语义的单个系统范围的零页.
推荐阅读
TXCWB_523
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有