Path: csiph.com!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: memcpy can't take null. Date: Sun, 05 Apr 2020 16:00:28 -0700 Organization: None to speak of Lines: 46 Message-ID: <87a73ppmgj.fsf@nosuchdomain.example.com> References: <6c3de07e-15c8-4cc0-a805-636a5976d086@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: reader02.eternal-september.org; posting-host="9aca32966cb66c1a01b4dff59d5f3d44"; logging-data="19654"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18KZ5sdMi7A7VNWzXv7GOTJ" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) Cancel-Lock: sha1:+eOWrW+0oheUd5z963JelrfZD/Q= sha1:cjgKxhEnL8+GJ10wDXy3GWvoZh4= Xref: csiph.com comp.lang.c:151104 Malcolm McLean writes: > memcpy() cannot take null as a pointer parametrer, even if the size argument > is zero. > > So what are the implications for passing empty buffers about? For example, > how would people write > > /* struct employee has no embedded pointers */ > > Employee *duplicateEmployees(Employee *employees, int Nemployees) C doesn't directly support empty arrays, but since arrays are usually manipulated via pointers to the initial element, it's easy enough to treat a pointer as pointing to an empty array. A null pointer doesn't point to an empty array. It doesn't point to *anything*. Similarly, a null pointer doesn't point to an empty string (there have been problems in the past with code that assumed it did, and that happened to "work" on some systems). Just keep that consistently in mind, and write your code in whatever way is necessary to maintain that. This might require a little special case code for handling the result of malloc(0). So write that code. Employee *duplicateEmployees(Employee *employees, size_t Nemployees) { const size_t requestedCount = Nemployees + (Nemployees == 0); Employee *const new = malloc(requestedCount * sizeof *new); if (new != NULL) { memcpy(new, employees, Nemployees * sizeof *new); } return new; } An alternative would be to treat a null pointer as a pointer to an empty array, but then you'd probably need more special case code on top of that to keep things consistent (to avoid passing null pointers to memcpy, for example). By *not* treating a null pointer as a pointer to an empty array, you can (probably) isolate the special case code to allocation functions. You'd also lose the ability to use a null pointer as a special value that doesn't point to anything. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Philips Healthcare void Void(void) { Void(); } /* The recursive call of the void */