I have 2 structs of the same size, layout and alignment, but of different types. I would like to copy one onto the other.
struct one s1;
struct two s2;
s1 = (struct one)s2; // error: conversion to non-scalar type requested
s1 = *((struct one*)&s2); // fine?
2nd method is portable as updated.
Converting object pointers types to
void* and back to original is fine. Between other pointer types may be UB. The trick is that even though the
two are the same size, we do not know they have the same alignment requirements which may differ because of their unposted members.
A pointer to
voidmay be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to
voidand back again; the result shall compare equal to the original pointer. C11dr §188.8.131.52 1
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. §184.108.40.206 7
OP details that "layout" (now "aliment") implies matching alignment (of all fields). If that is the case, then
s1 = *((struct one*)&s2); is acceptable.
For unquestionable portability, use
memcpy()/memmove() or consider a
assert(sizeof s1 == sizeof s2); memcpy(&s1, &s2, sizeof s1);
What was the thinking of the language designers here, are they making sure I take off the safety before I shoot myself in the foot?
s1 = *((struct one*)&s2);, you tell the compiler, "don't worry about the cast, I know what I am doing."
C was designed to be used by knowledgeable programmers to craft tight code who know when to cheat.
C is coding without a net
image at https://sparkfun.com.