Копирование части структуры с использованием memcpy и offsetof

#c #memcpy #offsetof

#c #memcpy #смещение

Вопрос:

Я хотел бы скопировать часть структуры, начиная с определенного элемента, путем объединения offsetof макроса и memcpy , как показано ниже:

 #include <stdio.h>
#include <string.h>
#include <stddef.h>

struct test {

  int x, y, z;
};

int main() {

  struct test a = { 1, 2, 3 };
  struct test b = { 4, 5, 6 };

  const size_t yOffset = offsetof(struct test, y);

  memcpy(amp;b   yOffset, amp;a   yOffset, sizeof(struct test) - yOffset);

  printf("%d ", b.x);
  printf("%d ", b.y);
  printf("%d", b.z);

  return 0;
}
  

Я ожидал, что это выведет, 4 2 3 но на самом деле выводится 4 5 6 так, как будто никакого копирования не было. В чем я ошибся?

Комментарии:

1. Пожалуйста, объясните ваше понимание / намерение каждой части memcpy(amp;b yOffset, amp;a yOffset, sizeof(struct test) - yOffset); .

2. Помните, что для любого указателя или массива p и индекса i выражение *(p i) равно p[i] . Из этого следует, что amp;b yOffset фактически равно (amp;b)[yOffset] . Это означает, что вы выходите за пределы своих структур. Вместо этого вы должны использовать указатели «байт».

3. Что касается «проблемы» и желаемого решения, какова актуальная проблема? Почему вам нужно копировать только часть структур? Почему вы думаете, что это лучшее (или единственное) решение вашей реальной основной проблемы?

4. Я думаю, что некоторые подразумевают, что мы смотрим на meta.stackexchange.com/questions/66377/what-is-the-xy-problem

5. @Someprogrammerdude Я читаю объектно-ориентированный C Акселя-Тобиаса Шрайнера, он делает что-то подобное для его реализации в vtable, но я не смог заставить его работать. Он на самом деле показывает кастинг в своей книге, но, честно говоря, я наивно проигнорировал это, думая, что это какой-то пережиток какой-то древней версии C. Мой плохой.

Ответ №1:

Вы выполняете арифметику указателя для указателя неправильного типа и записываете данные в некоторую случайную память в стеке.

Поскольку вы хотите вычислить смещения в байтах, вы должны использовать указатель на символьный тип. Так, например

 memcpy((char *)amp;b   yOffset, 
       (const char *)amp;a   yOffset, 
       sizeof(struct test) - yOffset);