Something has just occured to me.
In the solution I’ve accepted the struct padding is accessed via pointer casting, so basically without the compiler ‘knowing’ about my intention to use the padding bytes to store information.
Is the compiler allowed to clobber the padding of a struct? Could it, for example, use a 64 bit atomic for state because it’s faster on some system or whatever and just overwrite the 4 padding bytes after state on every write to it?
The C standard states:
J.1 Unspecified behavior
The following are unspecified:
[…]
— The value of padding bytes when storing values in structures or unions (6.2.6.1).
[…]
Is this also true for Zig? If it is what does this mean exactly and how could I solve this problem?
Yes it is allowed and in fact is already done for example for storing type safety information. If you want to reserve space within struct padding, simply declare the data as a field along with the others.
Thanks for the clarification this makes total sense!
I’ve actually come up with a (admittedly a little ridiculous) solution for finding the exact size the padding needs to be here. Maybe I should just admit defeat and use extern containers for things like this…
One of my concerns is that although the automatic alignment padding of structures may not be used to solve the semantics of false sharing, in practice many developers use this to improve multi-threaded performance. If the compiler can overwrite the structure padding, it may break the optimization assumptions that many developers make based on the structure padding to avoid false sharing.
Just to add an IME from the C world: don’t rely too much on ‘testing’ the behaviour of padding bytes because the situations where the padding bytes are not preserved are actually quite rare since the compiler will often use the equivalent of a memcpy to copy the structs around - until it doesn’t. One situation I’ve seen where padding-bytes may change is when structs are passed into functions by value, while just assigning one struct to another usually copied the entire memory area taken up by the struct.
E.g. this is a situation where in most situations it looks like padding bytes are preserved, but then there’s one place in the code where they arent.