Is it guaranteed to be safe to perform memcpy(0,0,0)?
I am not so well-versed in the C standard, so please bear with me.
I would like to know if it is guaranteed, by the standard, that memcpy(0,0,0)
is safe.
The only restriction I could find is that if the memory regions overlap, then the behavior is undefined...
But can we consider that the memory regions overlap here ?
Solution 1:
I have a draft version of the C standard (ISO/IEC 9899:1999), and it has some fun things to say about that call. For starters, it mentions (§7.21.1/2) in regards to memcpy
that
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.
The reference indicated here points to this:
If an argument to a function has an invalid value (such as a value outside the domain of the function, or a pointer outside the address space of the program, or a null pointer, or a pointer to non-modifiable storage when the corresponding parameter is not const-qualified) or a type (after promotion) not expected by a function with variable number of arguments, the behavior is undefined.
So it looks like according to the C spec, calling
memcpy(0, 0, 0)
results in undefined behavior, because null pointers are considered "invalid values."
That said, I would be utterly astonished if any actual implementation of memcpy
broke if you did this, since most of the intuitive implementations I can think of would do nothing at all if you said to copy zero bytes.
Solution 2:
Just for fun, the release-notes for gcc-4.9 indicate that its optimizer makes use of these rules, and for example can remove the conditional in
int copy (int* dest, int* src, size_t nbytes) {
memmove (dest, src, nbytes);
if (src != NULL)
return *src;
return 0;
}
which then gives unexpected results when copy(0,0,0)
is called (see https://gcc.gnu.org/gcc-4.9/porting_to.html).
I am somewhat ambivalent about the gcc-4.9 behaviour; the behaviour might be standards compliant, but being able to call memmove(0,0,0) is sometimes a useful extension to those standards.