With this definition:
struct vector {
const float x;
const float y;
};
would the code snippet below possibly result in undefined behavior?
struct vector src = {.x=1.0, .y=1.0};
struct vector dst;
void *dstPtr = &dst;
memcpy(dstPtr, &src, sizeof dst);
gcc
and clang
do not emit any warnings, but it does result in modification of a const-qualified type.
The construct looks a lot like the one given in the accepted answer to How to initialize const members of structs on the heap , which apparently is conformant. I do not understand how my example would therefore be non-conformant.
The
const
-qualifiers on members let the compiler assume that - after an object has been initialized - these members must not be altered through any way, and it may optimise code accordingly (cf, for example, @Ajay Brahmakshatriya comment).So it is essential to distinguish the initialization phase from the subsequent phases where assignments would apply, i.e. from when on may a compiler assume that an object got initialized and has an effective type to rely on.
I think there is a main difference between your example and that in the accepted answer you cited. In this SO answer, the target aggregate object with const-qualified member types is created through
malloc
:According to the rules on how a stored value of an object may be accessed (cf. this part of an online c standard draft), the
p
-target object will get its effective type the first time in the course of performingmemcpy
; the effective type is then that of the source objectinit
, and the firstmemcpy
on an object that gotmalloced
can be seen as an initialization. Modifying the target object's const members afterwards, however, would be UB then (I think that even a secondmemcpy
would be UB, but that's probably opinion based).In your example, however, the target object
dst
already has a declared type through it's definitionstruct vector dst;
. Hence, the const-qualifiers ondst
's members are already in place before thememcpy
is applied, and it has to be seen as an assignment rather than an initialization.So I'd vote for UB in this case.