0

I'd like to copy part of a struct starting from a certain element forward by combining the offsetof macro and memcpy, as shown below:

#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(&b + yOffset, &a + yOffset, sizeof(struct test) - yOffset);

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

  return 0;
}

I expected this to output 4 2 3 but it actually outputs 4 5 6 as if no copying had taken place. What did I get wrong?

Gian
  • 327
  • 2
  • 8
  • Please explain your understanding/intention of each part of `memcpy(&b + yOffset, &a + yOffset, sizeof(struct test) - yOffset);`. – Yunnosch Aug 31 '20 at 11:55
  • 1
    Remember that for any pointer or array `p` and index `i`, the expression `*(p + i)` is equal to `p[i]`. From that follows that `&b + yOffset` is actually equal to `(&b)[yOffset]`. This means you're going way out of bounds of your structures. You must use "byte" pointers instead. – Some programmer dude Aug 31 '20 at 11:56
  • 1
    Regarding the "problem" and the solution you want, what is the *actual* problem? Why do you need to copy only part of the structures? Why do you think that is the best (or only) solution to your actual underlying problem? – Some programmer dude Aug 31 '20 at 11:57
  • I think Some is implying that we are looking at a https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – Yunnosch Aug 31 '20 at 11:58
  • You might need the offset to calculate length to copy. But you can simply use `&b.y` to get address of that member. – Gerhardh Aug 31 '20 at 12:06
  • 1
    @Someprogrammerdude I'm reading Axel-Tobias Schreiner's Object Oriented C, he does something like this for its vtable implementation but I couldn't get it to work. He actually shows the casting in his book but honestly I naively ignored it, thinking it was some relic of some ancient version of C. My bad. – Gian Aug 31 '20 at 12:17
  • @Gerhardh it is in somewhat grey area... – Antti Haapala -- Слава Україні Aug 31 '20 at 12:19

1 Answers1

5

You're doing pointer arithmetic on a pointer of wrong type, and were writing to some random memory on stack.

Since you want to calculate byte offsets, you must use a pointer to a character type. So for example

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