Paul Eggert said:
I use these debugging options partly to check tzcode's portability. Although qsort(NULL, 0, ...) works fine on most practical platforms, as Clive noted there is (or was) an oddball platform or two that is (or was) verrrry picky about pointers, and for a program like zic where portability is more important than performance, it's nice if zic runs even on oddballs. Clive, do you happen to know what these platforms are (or were), and whether they're still supported?
Sorry, but I have no idea. We didn't always get told - if someone at the meeting said "I know an platform that does X", we believed them. There was a longstanding meme in the meetings (and on comp.std.c) that "if you don't understand the reasoning behing something in the C Standard, the answer is the IBM AS400".
As a practical matter, even though the C standard says that expressions like qsort(NULL, 0, ...) and (char *)NULL + 0 have undefined behavior, any new platform would be verrrry wise to define them to work the same way that most practical platforms do; this is true regardless of what the C standard says. And to some extent this means the C standard is not at the sweetest spot it could be in, as a contract between implementers and programmers. I write and see a lot of code where adding 0 to NULL is expected to yield NULL, and nobody thinks twice about it (nor should they).
Why not? You're assuming that NULL is represented by 32 or 64 zero bits [1]. That's not what all computers do. Unusual architectures may do something completely different and they might well trap on trying to add to a null pointer, irrespective of the value you're adding. This is, indeed, a modern version of the "all the world's a Vax" fallacy. [1] For those not used to this particular discussion, an integer *constant* that evaluates to zero, or one of those cast to a pointer type, is how you represent a null pointer. But that does not mean that: #define UCPSIZE (sizeof (unsigned char *)) union { unsigned char *p; char c [UCPSIZE]; } u; u.p = NULL; unsigned char z = 0; for (unsigned int i = 0; i < UCPSIZE; i++) z |= u.c [i]; printf ("Result = %u\n", z); is required to print zero. On the contrary, the representation of a null pointer is completely unspecified. -- Clive D.W. Feather | If you lie to the compiler, Email: clive@davros.org | it will get its revenge. Web: http://www.davros.org | - Henry Spencer Mobile: +44 7973 377646