Search code examples
cspecifications

Is structure self-assignment defined to be safe in C? Especially if one side is a pointer to the structure?


In the C language, is self-assignment of values well defined for structures?

struct Foo { char value[4096]; };

struct Foo foo = {0};

struct Foo *p_foo = &foo;

foo = *p_foo;

Is the value of foo defined after the assignment? Assume that the pointer is passed in from another function in another file, so that no compiler optimizations are possible (not that this is relevant to the spec).

This kind of assignment happens all of the time with simpler types like integers, but what about more complicated (and larger) structures?

In my testing, this appears to work as expected, but I'm trying to find out how strong that expectation should be.


Solution

  • In the C language, is self-assignment of values well defined for structures?

    Yes, self-assignment, whether via a pointer or otherwise, is well defined for all modifiable data types.

    I guess you're worried about some kind of problem with overlap, but semantically, when the expression on the right-hand side of an assignment is an lvalue, it is subject to lvalue conversion to produce a (transient) value prior to the effect of the assignment being performed or the value of the assignment expression being computed. Semantically, the initial value of the object is fully read, then its value is fully written (with the same contents, but see also below).

    The spec does say:

    If the value being stored in an object is read from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have qualified or unqualified versions of a compatible type; otherwise, the behavior is undefined.

    (C23 6.5.16.1/3)

    But that takes care to avoid preventing self-assignment.

    This kind of assignment happens all of the time with simpler types like integers, but what about more complicated (and larger) structures?

    The C language specification does not have different rules or provisions in this area for different modifiable data types. No matter how large or complex.

    In my testing, this appears to work as expected, but I'm trying to find out how strong that expectation should be.

    The spec says it works, in the sense that all the members will have the same values after the self-assignment as before. However,

    When a value is stored in an object of structure or union type, including in a member object, the bytes of the object representation that correspond to any padding bytes take unspecified values

    (C23 6.2.6.1/6)

    . It is possible to examine the padding bytes in a structure value that has any, and in that way one could conceivably observe a self-assignment of an object of structure type to have a recognizable effect. But I think that's unlikely in practice.