Note that there are some explanatory texts on larger screens.

plurals
  1. POCan a conforming C implementation #define NULL to be something wacky
    text
    copied!<p>I'm asking because of the discussion that's been provoked in <a href="https://stackoverflow.com/questions/2597142/when-was-the-null-macro-not-0/2597232">this thread</a>.</p> <p>Trying to have a serious back-and-forth discussion using comments under other people's replies is not easy or fun. So I'd like to hear what our C experts think without being restricted to 500 characters at a time. </p> <p>The C standard has precious few words to say about <code>NULL</code> and null pointer constants. There's only two relevant sections that I can find. First:</p> <blockquote> <h3>3.2.2.3 Pointers</h3> <p>An integral constant expression with the value 0, or such an expression cast to type void * , is called a null pointer constant. If a null pointer constant is assigned to or compared for equality to a pointer, the constant is converted to a pointer of that type. Such a pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.</p> </blockquote> <p>and second:</p> <blockquote> <h3>4.1.5 Common definitions </h3> <p>The macros are</p> <pre><code>NULL </code></pre> <p>which expands to an implementation-defined null pointer constant;</p> </blockquote> <p>The question is, can <code>NULL</code> expand to an implementation-defined null pointer constant that is different from the ones enumerated in 3.2.2.3? </p> <p>In particular, could it be defined as:</p> <pre><code>#define NULL __builtin_magic_null_pointer </code></pre> <p>Or even: </p> <pre><code>#define NULL ((void*)-1) </code></pre> <p>My reading of 3.2.2.3 is that it specifies that an integral constant expression of 0, and an integral constant expression of 0 cast to type void* must be among the forms of null pointer constant that the implementation recognizes, but that it isn't meant to be an exhaustive list. I believe that the implementation is free to recognize other source constructs as null pointer constants, so long as no other rules are broken. </p> <p>So for example, it is provable that </p> <pre><code>#define NULL (-1) </code></pre> <p>is not a legal definition, because in</p> <pre><code>if (NULL) do_stuff(); </code></pre> <p><code>do_stuff()</code> must not be called, whereas with</p> <pre><code>if (-1) do_stuff(); </code></pre> <p><code>do_stuff()</code> must be called; since they are equivalent, this cannot be a legal definition of <code>NULL</code>. </p> <p>But the standard says that integer-to-pointer conversions (and vice-versa) are implementation-defined, therefore it could define the conversion of -1 to a pointer as a conversion that produces a null pointer. In which case </p> <pre><code>if ((void*)-1) </code></pre> <p>would evaluate to false, and all would be well. </p> <p>So what do other people think? </p> <p>I'd ask for everybody to especially keep in mind the "as-if" rule described in <code>2.1.2.3 Program execution</code>. It's huge and somewhat roundabout, so I won't paste it here, but it essentially says that an implementation merely has to produce the same observable side-effects as are required of the abstract machine described by the standard. It says that any optimizations, transformations, or whatever else the compiler wants to do to your program are perfectly legal so long as the observable side-effects of the program aren't changed by them. </p> <p>So if you are looking to prove that a particular definition of <code>NULL</code> cannot be legal, you'll need to come up with a program that can prove it. Either one like mine that blatantly breaks other clauses in the standard, or one that can legally detect whatever magic the compiler has to do to make the strange NULL definition work. </p> <p>Steve Jessop found an example of way for a program to detect that <code>NULL</code> isn't defined to be one of the two forms of null pointer constants in 3.2.2.3, which is to stringize the constant:</p> <pre><code>#define stringize_helper(x) #x #define stringize(x) stringize_helper(x) </code></pre> <p>Using this macro, one could</p> <pre><code>puts(stringize(NULL)); </code></pre> <p>and "detect" that NULL does not expand to one of the forms in 3.2.2.3. Is that enough to render other definitions illegal? I just don't know. </p> <p>Thanks!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload