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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With