Struct initialization

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To initialize [non-global] structs, I typically use the syntax:

typedef struct {
	uint8_t foo1;
	uint16_t foo2;	
} myStruct1_t;

myStruct1_t test = {0};

However, I recently ran into an warning with a struct containing another struct. It claimed I was missing braces in the inialization.

typedef struct {
	myStruct1_t foo4;	
	uint8_t foo3;
} myStruct2_t;

myStruct2_t test2 = {0};  //Warning

I added a second pair of braces, and the warning went away.

myStruct2_t test2 = {{0}};

While this seems logical, I don't ever remember needing double braces before, and I have definitely used nested structs. Was the warning indicative of some other problem?

Edit: With some more testing, I think I figured it out. If the nested struct is FIRST, then the double braces are required. If the nested struct is NOT first, then it does not need double braces.

i.e.,

typedef struct {
	uint8_t foo3;
	myStruct1_t foo4;	
} myStruct2_t;

myStruct2_t test2 = {0};  //No Warning

has no warning, because foo3 is declared first in the struct definition.

Science is not consensus. Science is numbers.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hobbss wrote:
Edit: With some more testing, I think I figured it out. If the nested struct is FIRST, then the double braces are required. If the nested struct is NOT first, then it does not need double braces.

i.e.,

typedef struct {
	uint8_t foo3;
	myStruct1_t foo4;	
} myStruct2_t;

myStruct2_t test2 = {0};  //No Warning

has no warning, because foo3 is declared first in the struct definition.

test2.foo4 gets no warning because you have no explicit initializer for it.
It will be initialized because it is part of an initialized struct.
It will get the same initialization as if you had specified {0} for it.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do we have to distinguish here between global or static structures and local or automatic structures?
The question becomes more complex, if the first element is initialized to a non-zero value and the other elements are omitted...

In the beginning was the Word, and the Word was with God, and the Word was God.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Really? I thought that

struct foo s = { 0 };

would initialize all members to 0, regardless of lifetime, static/auto, whatever, and

struct foo s2 = { 1 };

would assign 1 to the first member, and 0 to all remaining members, again regardless of lifetime, static/auto, etc.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Omitted members in the initializer are set to 0 in whatever type they are (0.0 for float, NULL for pointers, etc). (Some compilers even let you omit all members.)

I really like C's named initializer feature, which allows me to initialize a structure without caring about the order of its members:

struct foo {
  int foo1;
  int foo2;
};

struct foo bar = { .foo2 = 2, .foo1 = 1 };

The same rules still apply to omitted members.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@blargg and christop: Thanks for the clarification.

Just wondering, how the compiler initializes a (big) static structure, where only one memeber is non-zero. If the data section is used, there will be a lot flash data wasted...

In the beginning was the Word, and the Word was with God, and the Word was God.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Just wondering

There's one easy way to find out ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, by the help of the lss file.
Assuming:

typedef struct
{
	unsigned char a;
	unsigned char b;
	unsigned char c;
	unsigned char d;
}  MY_STRUCT;

With

MY_STRUCT my_struct = { 2 };

or

MY_STRUCT my_struct = { .c=3 };

the loop for the data section initialization needs 4 bytes in flash memory.

The compiler is smart enough, to differentiate to

MY_STRUCT my_struct = { 0 };

,
so that it does not need further flash memory (bss section).

What do I learn?
If I have a big structure, e.g.

typedef struct
{
	unsigned char a[128];
	unsigned char b;
	unsigned char c;
	unsigned char d;
}  MY_STRUCT;

, where only a few members need to be initialized to a non-zero value, I should move the initialization to an init function, which is called before any access, to save flash memory (no data section needed for it).
On the other hand: Shouldn't this actually be the compiler optimizer's job, not the job of the programmer? ;-)

In the beginning was the Word, and the Word was with God, and the Word was God.