Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C initialize structure padding to zero?

Tags:

If a C compiler pads a structure in order to align the fields to their native alignment, and that structure is then initialized, is the padding initialized to zero?

For example the following structure:

typedef struct foo_t_ {     int  a;     char b;     int  c;     char d; } foo_t; 

On many systems this (poorly designed) structure would have a sizeof(foo_t) of 16, with a total of 6 bytes of padding, 3 bytes after each of the chars.

If we initialize the structure like:

foo_t foo = { .a = 1, .b = '2' }; 

then the fields foo.a will be set to 1 and foo.b will be set to the character '2'. The unspecified fields (`foo.c' and 'foo.d') will automatically be set to 0. The question is, what happens to the 6 bytes of padding? Will that also automatically be set to 0? or is it undefined behavior?

The use case is that I will be calculating hashes of data structures:

foo_t foo = { .a = 1, .b = '2' }; foo_t bar = { .a = 1, .b = '2' }; uint32_t hash_foo = calc_hash(&foo, sizeof(foo)); uint32_t hash_bar = calc_hash(&bar, sizeof(bar)); 

and I want to be sure that hash_foo and hash_bar are the same. I could guarantee this by first using memset() to clear the structures, then initializing them, but it seems cleaner to use C initialization instead.

In practice, GCC on my system does clear the padding as well, but I don't know if that is guaranteed.

like image 870
N. Leavy Avatar asked Jun 05 '16 12:06

N. Leavy


People also ask

Does C initialize struct to 0?

The basic game here is that: You don't have to initialise every element of a structure, but can initialise only the first one; you don't need nested {} even to initialise aggregate members of a structure. Anything in C can be initialised with = 0 ; this initialises numeric elements to zero and pointers null.

How does padding work in C struct?

Structure Padding in C:The structure padding is automatically done by the compiler to make sure all its members are byte aligned. Here 'char' is only 1 byte but after 3 byte padding, the number starts at 4 byte boundary. For 'int' and 'double', it takes up 4 and 8 bytes respectively.

Can we avoid structure padding?

In Structure, sometimes the size of the structure is more than the size of all structures members because of structure padding. Note: But what actual size of all structure member is 13 Bytes. So here total 3 bytes are wasted. So, to avoid structure padding we can use pragma pack as well as an attribute.

Why are C structs padded?

Structure padding is a concept in C that adds the one or more empty bytes between the memory addresses to align the data in memory.


1 Answers

In general, As per C11, for any uninitialized object chapter §6.2.6.1/6,

When a value is stored in an object of structure or union type, including in a member object, the bytes of the object representation that correspond to any padding bytes take unspecified values.

But, if the partial initialization is done, in that case, for rest of the members, the intialization happens as if an object that has static or thread storage duration, then, quoting the same standard, chapter §6.7.9/21

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

and regarding the implicit initialization of objects with static storage duration, paragraph 10

If an object that has static or thread storage duration is not initialized explicitly, then:

  • if it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;

So, in your case, padding for the remaining objects are guaranteed to be 0, but not for the members which has received the initializers.

So, all over, you should not depend on an implicit initialization of 0, use memset().

That being said, in anyway it's not recommended (required) to depend on padding bytes, if any. Use the exact member variables and calculate the hash based on those values.

like image 129
Sourav Ghosh Avatar answered Oct 30 '22 20:10

Sourav Ghosh