Подтвердить что ты не робот

Копирование одной структуры в другую

Я знаю, что я могу скопировать член структуры членом, вместо этого могу ли я сделать memcpy для структур?

Желательно ли это сделать?

В моей структуре у меня есть строка также как член, которую я должен скопировать в другую структуру, имеющую один и тот же элемент. Как это сделать?

4b9b3361

Ответ 1

Копирование с помощью простого назначения лучше всего, так как оно короче, легче читается и имеет более высокий уровень абстракции. Вместо того, чтобы говорить (читателю кода человека) "копировать эти биты отсюда до туда" и требовать от читателя думать о аргументе размера копии, вы просто выполняете простое задание ( "скопируйте это значение из здесь, чтобы здесь" ). Не может быть никаких сомнений относительно правильности размера.

Кроме того, если структура сильно заполнена, назначение может заставить компилятор испускать что-то более эффективное, поскольку ему не нужно копировать отступ (и он знает, где он), но mempcy() не так всегда будет копировать точное количество байт, которое вы скажете, чтобы скопировать.

Если ваша строка является фактическим массивом, то есть:

struct {
  char string[32];
  size_t len;
} a, b;

strcpy(a.string, "hello");
a.len = strlen(a.string);

Затем вы можете использовать простое назначение:

b = a;

Получить полную копию. Для данных переменной длины, смоделированных таким образом, однако, это не самый эффективный способ сделать копию, поскольку весь массив всегда будет скопирован.

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

В этих ситуациях "глубокая копия" на самом деле является единственным выбором, и это должно идти в функции.

Ответ 2

С C90 вы можете просто использовать:

dest_struct = source_struct;

пока строка запоминается внутри массива:

struct xxx {
    char theString[100];
};

В противном случае, если это указатель, вам нужно скопировать его вручную.

struct xxx {
    char* theString;
};

dest_struct = source_struct;
dest_struct.theString = malloc(strlen(source_struct.theString) + 1);
strcpy(dest_struct.theString, source_struct.theString);

Ответ 3

Если структуры имеют совместимые типы, да, вы можете, с чем-то вроде:

memcpy (dest_struct, source_struct, sizeof (dest_struct));

Единственное, что вам нужно знать, это то, что это мелкая копия. Другими словами, если у вас есть char *, указывающий на определенную строку, обе структуры будут указывать на одну и ту же строку.

И изменение содержимого одного из этих строковых полей (данные, на которые указывает char *, а не char *), также изменят другой.

Если вам нужна простая копия без необходимости вручную делать каждое поле, но с добавленным бонусом не-мелких копий строк, используйте strdup:

memcpy (dest_struct, source_struct, sizeof (dest_struct));
dest_struct->strptr = strdup (source_struct->strptr);

Это скопирует все содержимое структуры, затем глубоко скопирует строку, эффективно передавая отдельную строку каждой структуре.

И если ваша реализация C не имеет strdup (она не входит в стандарт ISO), получите ее здесь.

Ответ 4

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

struct {int a, b;} c, d;
c.a = c.b = 10;
d = c;

Ответ 5

  • Вы можете использовать структуру для чтения записи в файл.  Вам не нужно указывать его как `char *.  Размер структуры также будет сохранен.  (Этот вопрос не самый близкий к теме, но угадайте это: поведение в жесткой памяти часто напоминает RAM.)

  • Чтобы переместить (в и из) одно строковое поле, вы должны использовать strncpy  и прерывание последовательности '\0'.  Где-то вы должны помнить длину поля строки записи.

  • Чтобы переместить другие поля, вы можете использовать точечную нотацию, например:  NodeB->one=intvar;  floatvar2=(NodeA->insidebisnode_subvar).myfl;

    struct mynode {
        int one;
        int two;
        char txt3[3];
        struct{char txt2[6];}txt2fi;
        struct insidenode{
            char txt[8];
            long int myl;
            void * mypointer;
            size_t myst;
            long long myll;
             } insidenode_subvar;
        struct insidebisnode{
            float myfl;
             } insidebisnode_subvar;
    } mynode_subvar;
    
    typedef struct mynode* Node;
    
    ...(main)
    Node NodeA=malloc...
    Node NodeB=malloc...
    
  • Вы можете вставлять каждую строку в структуры, соответствующие ей,  чтобы уклониться от точки-2 и вести себя как Cobol:  NodeB->txt2fi=NodeA->txt2fi  ... но вам все равно потребуется переходная строка  плюс один strncpy, как указано в пункте-2 для scanf, printf  в противном случае оператор более длинный вход (короче),  не было бы усечено (с помощью пробелов).

  • (NodeB->insidenode_subvar).mypointer=(NodeA->insidenode_subvar).mypointer  создаст псевдоним указателя.
  • NodeB.txt3=NodeA.txt3  заставляет компилятор отклонить:  error: incompatible types when assigning to type ‘char[3]’ from type ‘char *’
  • point-4 работает только потому, что NodeB->txt2fi и NodeA->txt2fi принадлежат к одному и тому же typedef!!

    Правильный и простой ответ на эту тему я нашел в В C, почему я не могу назначить строку массиву char после объявления? "Массивы (также из символов) являются гражданами второго сорта в C".