Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are struct padding bytes preserved by member assignment?

Sample code:

#include <assert.h>

struct S
{
    unsigned char ch;
    int i;
};

int main()
{
    struct S s;

    memset(&s, 0, sizeof s);

    s.ch = 257; 

    assert( 0 == ((unsigned char *)&s)[1] );
}

Can the assertion fail?

The motivation for the question is whether a compiler on a little-endian system could decide to use a 4-byte store to implement s.ch = 257;. Obviously nobody would ever write code like I did in my example, but something similar might realistically occur if ch is assigned in various ways in a program which then goes on to use memcmp to check for struct equality.

For example, if the code does --s.ch instead of s.ch = 257 - can the compiler emit a word-size decrement instruction?

I don't think the discussion around DR 451 is relevant, as that only applies to uninitialized padding; however the memset initializes all the padding to zero bytes.

like image 322
M.M Avatar asked Sep 09 '26 06:09

M.M


1 Answers

Yes, it can fail. The behavior is unspecified, but not undefined.

After the assignment s.ch = 257;, the values of all padding bits take unspecified values1 , which means that, if the second byte of the structure is a padding byte, it takes unspecified value and the result of the comparison to zero isn't specified. It may trigger or not.

The read value in the assert cannot be a trap representation because unsigned char doesn't have trap representations, and because the value is unspecified, not indeterminate.


1 (Quoted from: ISO/IEC 9899:201x 6.2.6.1 General 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.

like image 168
2501 Avatar answered Sep 11 '26 17:09

2501



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!