What is the correct way to initialize a very large struct?

In our code we used to have something like this:

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

This used to work great, and then we upgraded versions of GCC and suddenly started seeing stack overflows. Looking at the assembly, the old GCC code (2.x) was basically doing this:

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

The new GCC (3.4.x) was doing this

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

After reviewing the C99 spec, I could see why; C99 basically requires that anonymous structures exist on the stack. It's a good concept, but this structure was 4 Megabytes large, and only ever intended to exist on heap!

We've resorted to making our own 'initialize' function that explicitly sets the members, but that's ugly and a maintenance headache. I don't consider memset a proper solution, because I can't know that a bit-value of 0 is an appropriate zero value for the type ( nit-picking, I know, but there you are; I don't mind that the compiler does it, because it can know )

What is the "correct", or at least best, way to initialize a large structure like this?

To furthur clarify why I think memset isn't a solution: The rules of initialization of members not explicitly initialized are the same as static initialization, and are as follows: - If it has pointer type, it is initialized to a null pointer; - If it has arithmetic type, it is initialized to ( positive or unsigned ) zero; ...

'memset' will set the memory to bit-pattern zero, which isn't necessarily the same thing. Imagine a system that doesn't use IEEE floating point numbers. Unusual, but supported by C. The representation of 0.0 doesn't have to mean "all-bits zero", it could be anything convenient to the processor.


memset is the way to go. You do not have many alternatives.

Do something like:

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

So that you only have to:

InitStruct(st, BigStruct);

And then use st as usual...

I do not get how "0" is not a valid "0" type for a struct. The only way to "mass initialize" a struct is to set all of its memory to a value; otherwise you would have to make extra logic to tell it to use a specific bit pattern per member. The best "generic" bit pattern to use is 0.

Besides - this is the same logic that you used when doing

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

Therefore I don't get your reluctance to use it :)

The first comment to this post made me do some research before I called him and idiot and I found this:

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

Very interesting; if I could vote-up a comment I would :)

That being said - your only option if you want to target archaic architectures with non-0 null values is still to do manual initialization to certain members.

Thanks Thomas Padron-McCarthy! I learned something new today :)


If you don't want to use memset, you could always declare a static copy of your struct and use memcpy, which will give similar performance. This will add 4 megs to your program but is probably better than setting individual elements.

That said, if GCC was using memset, and it was good enough previously, I would suggest it is good enough now.


As others have said, memset is the way to go. However, don't use memset on C++ objects, particularly those with virtual methods. The sizeof( foo ) will include the table of virtual function pointers, and doing a memset on that will cause serious grief.

If memset doesn't solve the problem by itself, simply do a memset and then initialize any members that should be non-zero (ie your non-IEEE floating point values).

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

上一篇: C的隐藏功能

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