C: делает ли оператор присваивания глубокое копирование? - PullRequest
0 голосов
/ 11 июня 2019

Для скалярных значений оператор присваивания, похоже, копирует правое значение влево. Как это работает для составных типов данных? Например, если у меня есть вложенная структура

struct inner {
    int b;
};

struct outer {
   struct inner a;
};

int main() {
   struct outer s1 = { .a = {.b=1}};   
   struct outer s2 = s1;
}
  • копирует ли присвоение рекурсивно глубокое значение?
  • происходит ли то же самое при передаче структуры в функцию?

Экспериментируя, кажется, что это так, но может ли кто-нибудь указать на спецификацию поведения?

Ответы [ 2 ]

4 голосов
/ 11 июня 2019

нет "рекурсии"; он копирует все биты (значения) значения. Конечно, за указателями магически не следят, оператор присваивания не знает, как дублировать указанные данные.

Вы можете думать о

a = b;

как сокращение для

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

sizeof вводит в заблуждение, конечно, поскольку мы знаем, что типы одинаковы с обеих сторон, но я не думаю, что __typeof__ помогает.

Проект спецификации C11 гласит (в пункте 6.5.16.1 Простое присвоение, пункт 2):

В простом присваивании (=) значение правого операнда преобразуется в тип выражения присваивания и заменяет значение, хранящееся в объекте обозначается левым операндом.

2 голосов
/ 11 июня 2019
  • копирует ли назначение рекурсивно глубокое копирование значений?

    Да, точно так же, как если бы вы использовали memcpy.Указатели копируются, но не то, на что они указывают.Термин «глубокое копирование» часто означает: также скопируйте то, на что указывают указатели (например, в конструкторе копирования C ++).

    За исключением того, что значения любых байтов заполнения могут содержать неопределенные значения.(Это означает, что memcmp в структуре может быть небезопасным.)

  • происходит ли то же самое при передаче структуры в функцию?

    Да.См. Ссылку на 6.5.2.2 ниже.

  • Экспериментируя, кажется, что это так, но может ли кто-нибудь указать на спецификацию поведения?

    C17 6.5.16:

    Оператор присваивания сохраняет значение в объекте, обозначенном левым операндом.Выражение присваивания имеет значение левого операнда после присваивания, но не является lvalue.Типом выражения присваивания является тип, который левый операнд будет иметь после преобразования lvalue.

    (Преобразование Lvalue в этом случае не имеет значения, поскольку обе структуры должны быть на 100% идентичными и совместимыми типамиПроще говоря: две структуры совместимы, если они имеют одинаковые члены.)

    C17 6.5.16.1 Простое назначение:

    • левый операнд имеет атомарный, квалифицированныйили неквалифицированная версия типа структуры или объединения, совместимая с типом права;

    C17 6.5.2.2 Вызовы функций, §7:

    Есливыражение, которое обозначает вызываемую функцию, имеет тип, который включает в себя прототип, аргументы неявно преобразуются, как если бы путем присваивания, ...

...