If two pointers are pointing to the same struct variable, is it defined behaviour to assign one dereferenced pointer to the other?
struct Struct {
int member;
};
int main() {
struct Struct s, *p1, *p2;
s.member = 1234;
p1 = p2 = &s;
*p1 = *p2; // is this allowed?
}
I mainly ask because in this SO post and this SO post a number of answers state that struct assignment is more or less equivalent to memcpy, and some compilers even generate a memcpy call for the assignment statement. However, memcpy is not defined when the memory locations overlap, which begs the question: is it defined for assignment?
This appears to be behaving as expected, but I would like to know if the C standard has anything to say about it. Is it necessary to add a simple check
if (p1 != p2) *p1 = *p2;
or use memmove instead?
FYI, this came up when I was implementing my own slot map (as described here) in C. When removing an element from the container, the element at the end of the array gets copied to the deleted location to keep everything contiguous. In the case where the deleted element is at the end of the array, it will get copied to itself (not super important since that element is considered to be deleted, but got me curious anyway).
The assignment is well defined. A corresponding call to
memcpywould not be.Here's what the standard says about simple assignment N1570 6.15.6.1 paragraph 3):
whereas for
memcpy(7.24.2.1 paragraph 2):So it's not correct that struct assignment is equivalent to
memcpy, though the "more or less" qualification is appropriate. For one thing, as we see here,memcpybetween exactly overlapping objects is undefined, while assignment is well defined. For another,memcpypreserves the values of any padding bytes (gaps between members or after the last one), while assignment is not guaranteed to do so. Assignment could be implemented by copying each member rather than by copying the entire structure.That being said, an implementation could implement assignment and
memcpyin exactly the same way. The fact that some cases have undefined behavior means that an implementation is free to do anything convenient.