0

Basically I need to do multiple memcpy() and I don't want to increment the destination pointer dst++; after every memcpy() call.. just wondering how to save some coding time.

memcpy(dest, src1, 1); // uint8_t
dest += 1;
memcpy(dest, src2, 2); // uint16_t
dest += 2;
memcpy(dest, src3, 1024); // uint8_t*
dest += 1024;
...

How to do multiple memcpy() that increment the destination pointer for you?

ShellX3
  • 51
  • 8
  • 1
    For example dest += 2; or memcpy(dest + 1, src2, 2); ? – Vlad from Moscow Nov 15 '21 at 18:18
  • @VladfromMoscow Thank you, True, incrementation in one line is a solution. – ShellX3 Nov 15 '21 at 18:24
  • `static inline void *CopyAndUpdate(void * restrict s1, const void * restrict s2, size_t n) { return (char *) memcpy(s1, s2, n) + n; }`, then `dest = CopyAndUpdate(dest, src1, 1); dest = CopyAndUpdate(dest, src1, 2);`. Or `static inline void CopyAndUpdate(char * restrict * s1, const void * restrict s2, size_t n) { memcpy(*s1, s2, n); *s1 += n; }`, then `CopyAndUpdate(&dest, src, 1); CopyAndUpdate(&dest, src, 2);`, presuming the type of `dest` is `char *`. – Eric Postpischil Nov 15 '21 at 18:25
  • @EugeneSh. True, but this is just an example, my real data up to 1024 * 4 bytes. – ShellX3 Nov 15 '21 at 18:25
  • @EricPostpischil Thank you Eric, your answer is complete. your function is exactly what I need. – ShellX3 Nov 15 '21 at 18:26
  • @EricPostpischil inlining will happen anyway. – 0___________ Nov 15 '21 at 18:28
  • @ShellX3 char size versison will not work for more than one byte size objects. Something more generic is needed. – 0___________ Nov 15 '21 at 18:36
  • @0__: In OP's example, `sizeof *dest` must be `1`, because otherwise it would not make sense that OP is passing `1` as the third parameter to `memcpy`. But you are right that the question is unclear in this respect. – Andreas Wenzel Nov 15 '21 at 19:11

2 Answers2

1

Write your own function.

for example generic for any size elements:

void *generic(void *dest, const void *src, const size_t elemsize, size_t nelems)
{
    char *cptr = dest;

    memcpy(dest, src, elemsize * nelems);
    cptr += nelems * elemsize;
    return cptr;
}

or as in your example (char size elements)

void *charSizeOnly(void *dest, const void *src, size_t nelems)
{
    char *cptr = dest;

    memcpy(dest, src, nelems);
    cptr += nelems;
    return cptr;
}

example usage:

    mytype *dest;
    mytype *src;
    /* ... some code*/
    /*it will copy and update the dest by 30 elements of type `mytype`*/
    dest = generic(dest, src, sizeof(*dest), 30); 

aschepler
  • 70,891
  • 9
  • 107
  • 161
0___________
  • 60,014
  • 4
  • 34
  • 74
1

You could make a function:

void memcpy_auto_inc( char **pp_dest, const void *src, size_t count )
{
    memcpy( *pp_dest, src, count );
    *pp_dest += count;
}

Now, assuming that dest is of type char*, instead of writing

memcpy( dest, src1, 1 );
dest += 1;
memcpy( dest, src2, 2 );
dest += 2;
memcpy( dest, src3, 1024 );
dest += 1024;

you can write:

memcpy_auto_inc( &dest, src1, 1 );
memcpy_auto_inc( &dest, src2, 2 );
memcpy_auto_inc( &dest, src3, 1024 );

However, I doubt that this is worth the effort, as it makes the code less clear and doesn't save you much typing, even if you select a much shorter name for the function than memcpy_auto_inc.

EDIT:

On request of OP, I will provide additional information regarding restrict and inline optimizations:

The function memcpy_auto_inc can be further optimized by changing the function prototype to use the restrict type qualifier:

void memcpy_auto_inc( char *restrict *restrict pp_dest, const void *restrict src, size_t count )

It would also be possible to add the inline function specifier. However, in my opinion, this is not necessary, as it is unlikely that this will result in increased run-time performance. You can generally rely on the compiler's optimizer to make the decision on whether it is appropriate to inline a function.

This topic is further discussed in this question:

When to use inline function and when not to use it?

However, that question is 12 years old and compiler's optimizers have improved significantly since then, so there is now even less reason to use the inline keyword.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • 1
    Side effects are one of the C devils. When not absolutely needed should be avoided at any price. `memcpy(dest, src2, 2); dest+=2;` is much better than `memcpy_auto_inc( &dest, src2, 2);` because it is obvious that the pointer is **modified** here – 0___________ Nov 15 '21 at 18:33
  • @0__: I agree. But OP asked for something other than `memcpy(dest, src2, 2); dest+=2;` that saves coding time. – Andreas Wenzel Nov 15 '21 at 19:26
  • But IMO it is the worst option. Why realloc returns value instead of taking the double pointer. To avoid SE – 0___________ Nov 15 '21 at 19:33
  • @AndreasWenzel, Can we use `restrict` and `inline` in your `memcpy_auto_inc()` for more optimization? – ShellX3 Nov 17 '21 at 14:27
  • @ShellX3: I have edited my answer to address your comment. – Andreas Wenzel Nov 17 '21 at 16:02
  • @AndreasWenzel Excellent explanation, Thank you Wenzel. – ShellX3 Nov 17 '21 at 16:38