[tz] [PROPOSED 1/7] Avoid undefined behavior if no Link lines

Clive D.W. Feather clive at davros.org
Thu Oct 27 06:38:42 UTC 2022


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 at davros.org     | it will get its revenge.
Web: http://www.davros.org  |   - Henry Spencer
Mobile: +44 7973 377646


More information about the tz mailing list