Использование offsetof
:
memcpy(&C, pA, offsetof(t_Object, next));
Причина в том, что t_Object
может иметь заполнение в конце, поэтому, если вы копируете все, кроме последних 8 байтов, вы можете копировать часть или всеуказатели.
Я не уверен, строго ли это соответствует - стандарт говорит, что вы можете скопировать целый объект, но я не уверен, что он говорит о частях объектов.
Это было бы немного странно, но представьте, что эта структура имеет некоторые отступы в середине, а некоторые в конце, и реализация заполняет все отступы в каждом объекте одинаковым байтовым значением, выбранным случайным образом, а затем проверяется, чтобы увидетьчто отступы все еще были последовательными.Я не думаю, что это запрещено.Тогда это не сработает.
На практике это довольно переносимо.В частности, элементы должны появляться в том порядке, в котором они определены, поэтому offsetof(t_Object, next)
определенно захватывает часть объекта вплоть до (но не включая) указателей.
Если вы можете изменитьструктура, тогда вы могли бы построить его из замененной части, а также не замененной части:
typedef struct payload {
signed int a[3];
double float b;
unsigned short int c[30];
} payload;
typedef struct s_Object {
payload data;
struct s_Object *next, *prev;
} t_Object;
Тогда поменять местами:
payload C = pA->data;
pA->data = pB->data;
pB->data = C;
Редактировать: подсказка memcpy против назначенияв C - должно быть memmove?
Последний также имеет то преимущество, что по стандарту гарантируется работа при pA == pB
.Тот, у которого memcpy
нет, потому что для второго экземпляра регионы перекрываются.Ни один из них не является оптимальным в случае самостоятельной замены, но, вообще говоря, они, вероятно, настолько редки, что не стоит проверять указатели, если это не требуется.