According to N1570 6.5/6:
If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one.
That would suggest that even on a system where "long" and some other integer type have the same representation, the following would invoke Undefined Behavior:
#if ~0UL == ~0U
#define long_equiv int
#elif ~0UL == ~0ULL
#define long_equiv long long
#else
#error Oops
#endif
long blah(void)
{
long l;
long_equiv l2;
long_equiv *p = malloc(sizeof (long));
l = 1234;
memcpy(p, &l, sizeof (long));
l2 = *p;
free(p); // Added to address complaint about leak
return l2;
}
since the data pointed to by l
clearly has effective type long
and the object pointed to by p
has no declared type, the memcpy
should set the effective type of the storage to long
. Since reading use of an lvalue of type long_equiv
to read an object with effective type of long
is not allowed, the code would invoke Undefined Behavior.
Given that prior to C99 memcpy
was one of the standard ways to copy data of one type to storage of another type, the new rules about memcpy
cause a lot of existing code to invoke Undefined Behavior. If the rule had instead been that using memcpy
to write to allocated storage leaves the destination without any effective type, the behavior would be defined.
Are there any compilers which do not behave as though memcpy
leaves the effective type of the destination unset when used to copy information to allocated storage, or should use of memcpy
for purposes of data translation be considered "safe"? If some compilers do apply effective type of the source to the destination, what would be the proper way of copying data in type-agnostic fashion? What is meant by "copied as an array of character type"?