There is no problem with memcpy other than that you can't use a null pointer. You can memcpy zero bytes as long as the pointer is valid. This works in a good many circumstances; just not circumstances where the empty array is represented by not having an address at all.<p>For instance, say we write a function that rotates an array: it moves the low M bytes to the top of the array, and shuffles the remaining M - N bytes down to the bottom. This function will work fine with the zero byte memmove or memcpy operations in the special case when N == 0, because the pointer will be valid.<p>Now say we have something like this:<p><pre><code> struct buf {
char *ptr;
size_t size;
};
</code></pre>
we would like it so that when the size is zero, we don't have an allocated buffer there. But we'd like to support a zero sized memcpy in that case: memcpy(buf->ptr, whatever, 0) or in the other direction likewise.<p>We now have to check for buf->ptr being buf in the code that deals with resizing.<p>Here is a snag in the C language related to zero sized arrays. The call malloc(0) is allowed to return a null pointer, or a non-null pointer that can be passed to free.<p>oops! In the one case, the pointer may not be used with a zero-sized memcpy; in the other case it can.<p>This also goes for realloc(NULL, 0) which is equivalent to malloc(0).<p>And, OMG I just noticed ...<p>In C99, this was valid realloc(ptr, 0) where ptr is a valid, allocated pointer. You could realloc an object to zero.<p>I'm looking at the April 2023 draft (N3096). It states that realloc(ptr, 0) is undefined behavior.<p>When did that happen?
Useful context on the Rust side is this issue [1]. It sounds like some of the author's concerns are addressed already.<p>[1]: <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues/472">https://github.com/rust-lang/unsafe-code-guidelines/issues/4...</a>
A fun additional twist to this is that dereferencing nullptr is valid in WebAssembly, and actual data can in fact end up there, though ideally it never will.<p>If you ensure that the 'zero page' (so to speak) is empty you can also exploit this property for optimizations, and in some cases the emscripten toolchain will do so.<p>i.e. if you have<p><pre><code> struct MyArray<T> {
uint length;
T items[0];
}
</code></pre>
you can elide null pointer checks and just do a single direct bounds check before dereferencing an element, because for a nullptr, (&ptr->length) == nullptr, and if you reserve the zero page and keep it empty, (nullptr)->length == 0.<p>this complicates the idea of 'passing nothing' because now it is realistically possible for your code to get passed nullptr on purpose and it might be expected to behave correctly when that happens, instead of asserting or panicking like it would on other (sensible) targets
I'm dealing with the exact same issues right now in my project, this post is very enlightening.<p>> But suppose we want an empty (length zero) slice.<p>So is there an actual rationale for this? I've written the memory allocator and am in the process of developing the foreign interface. I've been wondering if I should explicitly support zero length allocations. Even asked this a few times here on HN but never got an answer. It seems to be a thing people sort of want but for unknown reasons.
It's obviously too late to change this in Rust's case, but I wonder whether being able to differentiate between None and the empty slice is actually a necessary property in general?<p>There are a bunch of languages where empty arrays are "falsy", and in those it's not recommendable to use the two to differentiate valid states. Feels like the same could apply here
It’s so silly to talk about C not allowing null on memcpy. That’s a thing the spec says, I guess?<p>The solution is clear: just ignore the C spec. It’s total garbage. Of course you can memcpy between any ptr values if the count is zero and those ptr values don’t have to point to anything.
> Passing nothing is surprisingly difficult<p>From the title, I assumed that this article was going to be about either (a) permissive grading standards at university or (b) chronic constipation.