C:赋值运算符是否深拷贝?

C: does the assignment operator deep copy?

对于标量值,赋值运算符似乎将右侧的值复制到左侧。这对复合数据类型有何影响?例如,如果我有一个嵌套结构

struct inner {
    int b;
};

struct outer {
   struct inner a;
};

int main() {
   struct outer s1 = { .a = {.b=1}};   
   struct outer s2 = s1;
}

通过实验看起来确实如此,但任何人都可以指出行为的规范吗?

没有"recursion";它复制值的所有(值)位。当然,指针并没有神奇地跟随,赋值运算符不知道如何复制 pointed-to 数据。

你可以想到

a = b;

作为shorthand 对于

memcpy(&a, &b, sizeof a);

sizeof 当然是误导,因为我们知道两边的类型相同,但我认为 __typeof__ 没有帮助。

C11 规范草案说(在 6.5.16.1 简单赋值,第 2 段):

In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.

  • does the assignment recursively deep copy the values?

    是的,就像您会使用 memcpy 一样。指针被复制,但不是它们指向的内容。术语 "deep copy" 通常意味着:同时复制指针指向的内容(例如在 C++ 复制构造函数中)。

    除了任何填充字节的值可能包含不确定的值。 (这意味着结构上的 memcmp 可能不安全。)

  • does the same happen when passing the struct to a function?

    是的。请参阅下面对 6.5.2.2 的引用。

  • By experimenting it seems like it does, but can anyone point to the specification of the behavior?

    C17 6.5.16:

    An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion.

    (在这种情况下,左值转换不相关,因为两个结构必须是 100% 相同且兼容的类型。简单地说:如果两个结构具有完全相同的成员,则它们是兼容的。)

    C17 6.5.16.1 简单赋值:

    • the left operand has an atomic, qualified, or unqualified version of a structure or union type compatible with the type of the right;

    C17 6.5.2.2 函数调用,§7:

    If the expression that denotes the called function has a type that does include a prototype, the arguments are implicitly converted, as if by assignment, ...