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.
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.
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