Can memcpy or memmove return a different pointer than dest?

Question

The function memmove is defined like this:

void *memmove(void *dest, const void *src, size_t n);

In the Linux manual page, it says:

RETURN VALUE
The memmove() function returns a pointer to dest.

Why isn't the function just defined as void memmove(…) when it always returns one of the input parameters? Can the return value be different from dest?

Or is the return value really always dest and it is just done to be able to compose the function in some creative ways?


Show source
| C   | return-value   | function-call   | memmove   2016-10-12 15:10 3 Answers

Answers ( 3 )

  1. 2016-10-12 15:10

    As per C11, chapter §7.24.2.1 and §7.24.2.2

    void *memcpy(void * restrict s1, const void * restrict s2, size_t n);

    [...] The memcpy function returns the value of s1.

    and,

    void *memmove(void *s1, const void *s2, size_t n);

    [...] The memmove function returns the value of s1.

    So, the functions will always return the pointer to the destination buffer, that's by design.

    Now coming to the why part, many functions are designed this way to make chaining of function calls possible. That way, you can have a call to memmove() as an argument to another function, where the copied value (i.e, the pointer to dest) is going to be of some use.

    For example, you can write the shorter one

     puts(memmove(dest_buffer, src_buffer, welcome_message_size));
    

    instead of the longer one

     memmove(dest_buffer, src_buffer, welcome_message_size);
     puts(dest_buffer);
    
  2. 2016-10-12 15:10

    memmove will never return anything other than dest.

    Returning dest, as opposed to making memmove void, is useful when the first argument is a computed expression, because it lets you avoid computing the same value upfront, and storing it in a variable. This lets you do in a single line

    void *dest = memmove(&buf[offset] + copiedSoFar, src + offset, sizeof(buf)-offset-copiedSoFar);
    

    what you would otherwise need to do on two lines:

    void *dest = &buf[offset] + copiedSoFar;
    memmove(dest, src + offset, sizeof(buf)-offset-copiedSoFar);
    
  3. 2016-10-12 16:10

    The idiom of returning the exact value of one of the arguments (of pointer type) exists in order to support "chained" function calls (also see strcpy, strcat etc). It allows you to write some repetitive code as a single expression statement instead of splitting it into multiple statements. For example

    char buffer[1024];
    printf("%s\n", strcat(strcat(strcpy(buffer, "Hello"), " "), "World"));
    
    struct UserData data_copy;
    some_function(memcpy(&data_copy, &original_data, sizeof original_data));
    

    Even if you don't like this style of organizing code and prefer doing the same through multiple statements, the overhead of returning an [unnecessary] pointer value is virtually non-existent.

    One can even say that the value of this idiom increased a bit after the introduction of compound literals in C99. With compound lterals this very idiom allows one to write the same code without introducing a named intermediate variable

    printf("%s\n", strcat(strcat(strcpy((char [1024]) {}, "Hello"), " "), "World!"));
    
    some_function(memcpy(&(struct UserData) {}, &original_data, sizeof original_data));
    

    which makes sense since in most cases that named variable is supposed to be short-lived, is not needed afterwards, and only clutters the namespace.

◀ Go back