1. 33
  1.  

    1. 5

      While academically interesting, this is more like a look into the unsound implications of the C standard than real advice like namesake unicode article. But that doesn’t mean it can’t be fun.

      For example, with #11, I’m doubtful that any C compiler which encourages (void*)x for creating a pointer to address 0 is going to be so standards compliant that it will also ensures x == NULL is false. But this makes me think that it could be a really silly challenge to make some sore of IOCC type competition to write an adversarial standards-compliant compiler, but require competitors to write code that still worked against it.

      1. 4

        Next up: an architecture that stores memory addresses in IEEE-754 floats.

        Is it my beloathed asm.js?

        1. 3

          There have been some, uh, “interesting times” around pointer arithmetic on NULL pointers. There’s the classic

          #define offsetof(type, member) \
                  ((size_t)&((type *)NULL)->member)
          

          which used to be really common, but nowadays it’s obligatory to use a compiler builtin instead.

          And there are all sorts of issues that often turn up in generic C++ where you do something like,

          for(mytype *end = ptr + len;
              ptr < end;
              ptr++)
          { … }
          

          which is a problem because NULL + 0 is forbidden even though it seems to be a no-op — well, it was a problem, but it is so common that NULL + 0 is becoming permitted.

          1. 1

            Well, offsetof() is defined by the C standard (even as far back as C89) so there’s no need to define it, but using it, in my opinion, feels dodgy because of all the casts that need to be done:

            static inline const__s *enum_from_node(Node *node) 
            { 
              return (const__s *)(((char *)node) - offsetof(const__s, value.enumeration.node));
            }
            

            As for your example, why is ptr NULL? Is this just an example of NULL + 0?

            1. 1

              WRT offsetof() I was talking about how implementations used to define it, e.g., but can’t with modern compilers.

              WRT why ptr is NULL, because that’s the value it might happen to have due to whatever is going on in some wider context. If the language forbids NULL + 0 then most data structure code has to have redundant defensive NULL checks even when the code should be a no-op because the length is zero. This is a particular problem in C++ because its iterators are start / end not start / length. If NULL + 0 is permitted, then the compiler cannot assume that ptr != NULL when it sees ptr + len.

          2. 2

            This is a great list of things to avoid when writing a new language specification.