Can I call memcpy() and memmove() with "number of bytes" set to zero?

43,344

Solution 1

From the C99 standard (7.21.1/2):

Where an argument declared as size_t n specifies the length of the array for a function, n can have the value zero on a call to that function. Unless explicitly stated otherwise in the description of a particular function in this subclause, pointer arguments on such a call shall still have valid values, as described in 7.1.4. On such a call, a function that locates a character finds no occurrence, a function that compares two character sequences returns zero, and a function that copies characters copies zero characters.

So the answer is no; the check is not necessary (or yes; you can pass zero).

Solution 2

As said by @You, the standard specifies that the memcpy and memmove should handle this case without problem; since they are usually implemented somehow like

void *memcpy(void *_dst, const void *_src, size_t len)
{
    unsigned char *dst = _dst;
    const unsigned char *src = _src;
    while(len-- > 0)
        *dst++ = *src++;
    return _dst;
}

you should not even have any performance penality other than the function call; if the compiler supports intrinsics/inlining for such functions, the additional check may even make the code a micro-little-bit slower, since the check is already done at the while.

Share:
43,344

Related videos on Youtube

sharptooth
Author by

sharptooth

Updated on July 08, 2022

Comments

  • sharptooth
    sharptooth almost 2 years

    Do I need to treat cases when I actully have nothing to move/copy with memmove()/memcpy() as edge cases

    int numberOfBytes = ...
    if( numberOfBytes != 0 ) {
        memmove( dest, source, numberOfBytes );
    }
    

    or should I just call the function without checking

    int numberOfBytes = ...
    memmove( dest, source, numberOfBytes );
    

    Is the check in the former snippet necessary?

    • Toad
      Toad over 13 years
      question reminds me a bit of checking for null pointers on functions like free. Not necessary, but I would put a comment there to show you thought about it.
    • josesuero
      josesuero over 13 years
      @Toad: What purpose does that serve, other than to clutter up the code? When reading someone's code, I don't need to know that the original programmer "thought about doing this operation which isn't actually necessary, but because it's unnecessary, I didn't do it". If I see a pointer beeing freed, I know it is allowed to be null, so I don't need to know the thoughts of the original programmer on the subject of "should I check for null". And the same goes for copying 0 bytes with memcpy
    • Toad
      Toad over 13 years
      @jalf: the fact that it is a question on stackoverflow, makes it something people doubt. So adding a comment may not help you, but might help someone with less knowledge
    • Mark Amery
      Mark Amery over 5 years
      @Toad Yeah, comments explicitly calling out why a check that looks necessary really isn't can be valuable in principle. The other side of the coin is that this particular example is a common case involving a standard library function that each programmer only needs to learn the answer to once; then they can recognise in any program they read that these checks aren't needed. For that reason, I'd omit the comments. A codebase with multiple calls like this is either gonna need to copy and paste the comments to each one, or arbitrarily use them on only some calls, both of which are ugly.
  • Toad
    Toad over 13 years
    I would think this function is probably made in assembly where you can optimize memory tranfers much better than in c
  • Matteo Italia
    Matteo Italia over 13 years
    "somehow like" :) Actually almost all the implementations I've seen are in assembly, and try to copy most of the bits using the native word size (e.g. uint32_t on x86), but that doesn't change the substance of the answer: it's a while loop that doesn't need great calculations before starting, so the check is already done.
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE over 13 years
    -1, the typical implementation is irrelevant to whether it's valid C to call these functions (which may not even be implemented as C functions) with a zero argument.
  • Matteo Italia
    Matteo Italia over 13 years
    The fact that it's valid C has already been covered by the other answers, as I said at the very beginning of my answer: "As said by @You, the standard specifies that the memcpy and memmove should handle this case without problem". I just added my opinion on the fact that you should not even have fear of calling memcpy with len=0 for performance reasons, since in that case it's a call with an almost zero cost.
  • supercat
    supercat over 12 years
    Would a pointer be considered "valid" for purposes of such a function if it pointed to the location following the last element of an array? Such a pointer could not be legitimately deferenced, but one could safely do some other pointer-ish things like subtract one from it.
  • Mike Seymour
    Mike Seymour over 12 years
    @supercat: yes, a pointer that points one past the end of an array is valid for pointer arithmetic with other pointers within (or one past the end of) that array, but is not dereferencable.
  • neverhoodboy
    neverhoodboy about 10 years
    @MikeSeymour: Shouldn't the citation imply an opposite answer: the check is necessary and you can't pass zero with null pointers?
  • Mike Seymour
    Mike Seymour about 10 years
    @neverhoodboy: No, the quote clearly says "n can have the value zero". You're correct that you can't pass null pointers, but that's not what the question is asking about.
  • neverhoodboy
    neverhoodboy about 10 years
    @MikeSeymour: My fault. Really sorry. The question is about the size not the pointer.
  • Jim Balter
    Jim Balter almost 4 years
    "You're correct that you can't pass null pointers, but that's not what the question is asking about." The OP didn't specify what source is. Very often in these cases where the length is 0, the address being copied is NULL. In those cases, the standard requires a check--but you can usually get away without it, since memmove doesn't check and implementations where NULL is a trap value are nonexistent AFAIK.