Does any compiler provide an efficient transfer type via memcpy / memmove

According to N1570 6.5 / 6:

If the value is copied to an object without an declared type using memcpy or memmove or copied as an array of symbol type, then the effective type of the changed object for this access and for subsequent calls that do not change the value is the effective type of the object from which the value is copied, if it there is.

This assumes that even on a system where "long" and some other integer type have the same representation, the following calls 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 an effective type of long , and the object pointed to by p has no declared type, memcpy must set the effective storage type to long . Since reading an lvalue of type long_equiv to read an object with an effective type of long not allowed, the code will call Undefined Behavior.

Given that, prior to C99, memcpy was one of the standard ways of copying data of one type to store another type, the new memcpy rules cause a lot of existing code to call Undefined Behavior. If the rule were that using memcpy to write to dedicated storage leaves the destination without any efficient type, the behavior would be determined.

Are there any compilers that don’t behave as if memcpy n’t deleting the effective recipient type if it is used to copy information to dedicated storage, or should memcpy use it to translate data as “safe”? If some compilers really apply an efficient source type to their destination, what would be the correct way to copy data in an agnostic style? What does "copied as an array of character type" mean?

+6
source share
2 answers

The C standard says that the effective type is passed. Therefore, by definition, all relevant compilers pass an efficient type.

The sample code causes undefined behavior, violating the strict alias rule, because the value of the effective long type is read by the value l of the long long type.

This is also true in C89, I'm not sure what you are talking about "new rules in C99" (except that long long not in C89).

It is true that when C is standardized, some existing code had undefined behavior. And it’s also true that people continue to write code with undefined behavior.

What is meant by "copied as an array of character type"?

This means that you need to copy incremental characters using a character type.

What would be the correct way to copy data in an agnostic style?

It’s impossible to “erase the effective type”, as far as I know. To correctly read the value using long long * , you must point to the location of the effective type long long long long * .

In your code, for example:

 // If we have confirmed that long and long long have the same size and representation long long x; memcpy(&x, p, sizeof x); return x; 

Another option is channel merging.

If you don't like all this then compile with -fno-strict-aliasing .

+2
source
Experimentally, gcc 6.2 behaves the way it would be justified, considering memmove as a transfer of an effective source type to its destination. If gcc can determine that the source and destination pointers match, it will process the memory operand as soon as it is readable through its earlier effective type, and not as the memory that was last written using the character type, and therefore it can be accessed using any type. Such behavior would be unjustified without a rule allowing memcpy transmit information of an efficient type.

On the other hand, gcc behavior can sometimes not be justified under any rule, so it is not necessarily clear whether gcc behavior is a consequence of the interpretation of its authors by the Standard or simply broke it. For example, if it can determine that the memcpy target contains the same constant bit pattern as the source, then it will treat memcpy as no-op, even if the type was saved in the source, which will then be used to read the target storage. and the destination, which was assigned by another type, the compiler decided not to have an alias for the next read.

+2
source

All Articles