Can I call memcpy() and memmove() with "number of bytes" set to zero?
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.
Related videos on Youtube
sharptooth
Updated on July 08, 2022Comments
-
sharptooth almost 2 years
Do I need to treat cases when I actully have nothing to move/copy with
memmove()
/memcpy()
as edge casesint 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 over 13 yearsquestion 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 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 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 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 over 13 yearsI would think this function is probably made in assembly where you can optimize memory tranfers much better than in c
-
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 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 over 13 yearsThe 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 over 12 yearsWould 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 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 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 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 about 10 years@MikeSeymour: My fault. Really sorry. The question is about the size not the pointer.
-
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, sincememmove
doesn't check and implementations where NULL is a trap value are nonexistent AFAIK.