Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is zero initialization of structures guaranteed to wipe padded areas?

Suppose I have the following structure:

typedef struct
{
    unsigned field1 :1;
    unsigned field2 :1;
    unsigned field3 :1;
} mytype;

The first 3 bits will be usable but sizeof(mytype) will return 4 which means 29 bits of padding. My question is, are these padding bits guaranteed by the standard to be zero initialized by the statement:

mytype testfields = {0};

or:

mytype myfields = {1, 1, 1};

Such that it's safe to perform the following memcmp() on the assumption that bits 4..29 will be zero and therefore won't affect the comparison:

if ( memcmp(&myfields, &testfields, sizeof(myfields)) == 0 )
    printf("Fields have no bits set\n");
else
    printf("Fields have bits set\n");
like image 483
Benj Avatar asked Oct 24 '12 19:10

Benj


People also ask

What is zero initialization?

Setting the initial value of an object to zero is called the zero initialization.

How do you initialize all elements of a structure to zero?

Anything in C can be initialised with = 0 ; this initialises numeric elements to zero and pointers null.

Are class members zero initialized?

If T is scalar (arithmetic, pointer, enum), it is initialized from 0 ; if it's a class type, all base classes and data members are zero-initialized; if it's an array, each element is zero-initialized.

How do you initialize a structure?

An initializer for a structure is a brace-enclosed comma-separated list of values, and for a union, a brace-enclosed single value. The initializer is preceded by an equal sign ( = ).


2 Answers

Yes and no. The actual standard, C11, specifies:

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 this only holds for objects of static storage, at a first view. But then later it says in addition:

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.

So this means that padding inside sub-structures that are not initialized explicitly is zero-bit initialized.

In summarry, some padding in a structure is guaranteed to be zero-bit initialized, some isn't. I don't think that such a confusion is intentional, I will file a defect report for this.

Older versions didn't have that at all. So with most existing compilers you'd have to be even more careful, since they don't implement C11, yet. But AFAIR, clang already does on that behalf.

Also be aware that this only holds for initialization. Padding isn't necessarily copied on assignment.

like image 71
Jens Gustedt Avatar answered Oct 31 '22 00:10

Jens Gustedt


The C99 standard doesn't specify the padding bits would be set to zero. In fact, it specifically mentions that the values of any padding bits are unspecified, so that padding need not be copied in an assignment.

Footnote 51 to 6.2.6.1 (6) (n1570):

Thus, for example, structure assignment need not copy any padding bits.

The new C2011 standard - thanks to Jens Gustedt for sharing that knowledge - specifies that padding bits in objects of static or thread storage duration without explicit initialisation are initialised to 0.

There are still no guarantees for assignment.

like image 6
Daniel Fischer Avatar answered Oct 30 '22 23:10

Daniel Fischer