Копирование одной структуры в другую
Я знаю, что могу скопировать элемент структуры по элементу, вместо этого я могу сделать memcpy структур?
целесообразно ли это делать?
в моей структуре, у меня есть строка также членом которой я должен скопировать в другую структуру, имеющую тот же член. Как мне это сделать?
7 ответов
копирование простым назначением лучше всего, так как оно короче, легче читать и имеет более высокий уровень абстракции. Вместо того, чтобы говорить (человеческому читателю кода) "скопируйте эти биты отсюда туда" и требовать от читателя подумать о аргументе размера копии, вы просто выполняете простое назначение ("скопируйте это значение отсюда сюда"). Не может быть никаких сомнений в том, является ли размер правильным.
кроме того, если структура сильно проложена, назначение возможно, компилятор испустит что-то более эффективное, так как ему не нужно копировать заполнение (и он знает, где оно находится), но mempcy() не так, чтобы он всегда копировал точное количество байтов, которое вы говорите ему копировать.
Если ваша строка является фактическим массивом, то есть:
struct {
char string[32];
size_t len;
} a, b;
strcpy(a.string, "hello");
a.len = strlen(a.string);
тогда вы все еще можете использовать простое назначение:
b = a;
чтобы получить полную копию. Для данных переменной длины, смоделированных таким образом, это не самый эффективный способ сделать копию поскольку весь массив всегда будет скопирован.
остерегайтесь, однако, что копирование структур, содержащих указатели на память, выделенную кучей, может быть немного опасным, так как при этом вы псевдоним указатель и, как правило, делает его неоднозначным, кому принадлежит указатель после операции копирования.
для этих ситуаций "глубокая копия" - действительно единственный выбор, и это должно идти в функции.
начиная с 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);
если структуры имеют совместимые типы, да, вы можете, что-то вроде:
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);
это скопирует все содержимое структуры, затем глубоко скопируйте строку, эффективно давая отдельную строку каждой структуре.
и, если реализации не было!--5--> (это не входит в стандарт ISO), получить один отсюда.
Вы можете memcpy structs, или вы можете просто назначить их как любое другое значение.
struct {int a, b;} c, d;
c.a = c.b = 10;
d = c;
вы можете использовать структуру для чтения записи в файл. Вам не нужно бросать его как ' char*. Размер структуры также будет сохранен. (Этот момент не ближе к теме, но угадайте его: поведение на жесткой памяти часто похоже на RAM one.)
для перемещения (в & из) одного строкового поля необходимо использовать
strncpyи переходный строковый буфер''завершение. Где-то вы должны помнить длину строки записи поле.-
для перемещения других полей можно использовать точечную нотацию, например.:
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 и вести себя как Кобол:
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 *’ -
точка-4 работает только потому что
NodeB->txt2fi&NodeA->txt2fiпринадлежат к той жеtypedef!!правильный и простой ответ на эту тему я нашел в в C, почему я не могу назначить строку массиву символов после его объявления? "Массивы (также chars) являются гражданами второго класса в C"!!!
вы можете использовать следующее решение для достижения своей цели:
struct student
{
char name[20];
char country[20];
};
void main()
{
struct student S={"Wolverine","America"};
struct student X;
X=S;
printf("%s%s",X.name,X.country);
}
в C memcpy только глупо рискованно. Пока вы получаете все три параметра точно правильно, ни один из членов структуры не является указателем (или вы явно намереваетесь сделать мелкую копию), и в структуре нет больших пробелов в выравнивании, которые memcpy будет тратить время на цикл (или производительность никогда не имеет значения), тогда, безусловно, memcpy. Вы не получаете ничего, кроме кода, который сложнее читать, хрупкий для будущих изменений и должен быть проверен вручную в обзорах кода (потому что компилятор не могу), но эй, да, конечно, почему бы и нет.
В C++ мы переходим к смехотворно рискованному. У вас могут быть члены типов, которые небезопасны для memcpyable, например std::string, что заставит вашу принимающую структуру стать опасным оружием, случайным образом повреждая память при использовании. Вы можете получить сюрпризы, связанные с виртуальными функциями при эмуляции срез-копий. Оптимизатор, который может делать удивительные вещи для вас, потому что он имеет гарантию полного знания типа при компиляции =, может сделать ничего для вашего звонка memcpy.
в C++ есть эмпирическое правило - если вы видите memcpy или memset, что-то не так. Есть редкие случаи, когда это не так, но они не включают структуры. Вы используете memcpy, когда и только когда у вас есть причина слепо скопировать байт.
назначение, с другой стороны, просто читать, проверяет правильность во время компиляции, а затем разумно перемещает значения во время выполнения. Нет нижняя сторона.