avoiding incorrect code

Barry Smith bsmith at mcs.anl.gov
Wed Jan 14 16:56:54 CST 2009


On Jan 14, 2009, at 4:07 PM, Matthew Knepley wrote:

> I have no problem with this convention. However, I just checked the  
> C standard,
> and on page 254, in the stddef.h section, it says
>
>   NULL is an implementation specific null pointer constant.

    Yes this is correct, but there is more to it than that

C99 specs (aka ISO/IEC 9899:1999), This is what is says about null  
pointers in 6.3.2.3.3 and 6.3.2.3.4:

3. An integer 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 converted to a pointer type, the resulting  
pointer, called a null pointer, is guaranteed to compare unequal to a  
pointer to any object or function.
4. Conversion of a null pointer to another pointer type yields a null  
pointer of that type. Any two null pointers shall compare equal.

In other words if I do  void *ptr = (void *) 0 then ptr is A null  
pointer.  Also if I do if (ptr == NULL) it is always true.

It is a little funky, the standard does not say that a null pointer  
has to have a representation of all bits equal to zero. But it does  
say that if I write (void*) 0 in my code the compiler MUST represent  
it as a null pointer. The standard doesn't say that there has to be  
only a SINGLE null pointer representation. It could be that NULL has a  
different bit representation than (void*) 0 but the standard says that  
that NULL == (void*) 0 has to return true.

This imposes enough constraints that no sane person would implement  
NULL as anything but all zero bits, though it is allowed.

But I am still dancing around the issue. The issue is what does if (! 
ptr) have to return; the standard doesn't seem to say anything about  
this. In fact what does negation of a pointer mean? It could mean  
negate each bit of the pointer, and return true if any of the bits is  
1, but that is kind of a stupid definition. Any sane person would have  
the compiler define if (!ptr) to mean if (ptr == NULL) in the same way  
that if (!an_int) is defined as if (an_int == 0) Note that (!an_int)  
does NOT mean negate each bit of an_int and return true if any bits  
are nonzero.



All of this demonstrates that it would be legal that that (!ptr) is  
not correct and one should always use if (ptr == NULL). On the other  
hand no sane person would implement such a compiler because it would  
make the system unneccesarily complicated and unnatural. In addition,  
a huge percentage of C codes use if (!ptr) so even if someone did  
implement this insane compiler most C code wouldn't even work properly.

Thus I submit that it is perfectly fine to use if (!ptr) in the PETSc  
code.  Stylistically I find (ptr == NULL) very ugly (why have a !  
symbol if you don't use it?) and a sign that the programmer is trying  
to show off his subtle knowledge of the C standard.

   Barry

















>
>
> So technically, it does not have to be 0.
>
>    Matt
>
> On Wed, Jan 14, 2009 at 4:00 PM, Barry Smith <bsmith at mcs.anl.gov>  
> wrote:
>
> On Jan 14, 2009, at 3:37 PM, Satish Balay wrote:
>
> There are tonnes of places in PETSc with this usage [which I guess is
> fixable].
>
>   I have already pushed to petsc-3.0.0 the fixes for this. Virtually  
> all were Matt's
> fault in strange parts of the code no body uses so they don't matter  
> and then in
> the VecSetValues_ code.
>
>
> But imposing coding guidelines [which are unenforceable] to hide
> compiler differences is a bad policy..
>
>     This has nothing to do with compiler differences; just because  
> some Fortran
> compilers use the bit pattern of 1 for .true. and some use -1 does  
> not change
> the fact that a PetscTruth value of 0 is false while any other value  
> is true.
>
>  Using integers as boolean on the Fortran side is a perversity that  
> had to be
> fixed.
>
>
> It will continue to waste
> time..
>
>  In C the test if (something) and if (!something) means in the first  
> case
> if the value of something is NOT 0 and the second means the value of  
> something
> is 0. Hence, since C does not have a boolean value traditionally  
> people have
> taken true to be any nonzero value and false to be the zero value.  
> In fact,
> if you stick any nonzero value into a Fortran boolean it will treat  
> it as true;
> so Fortran also follows this paradigm. It is just when .true. is  
> used, the bit string
> of 1 or -1 is put in.
>
>  I don't know where the == PETSC_TRUE nonsense came from, it could be
> my fault. But the coding standard has been there for many years and  
> most
> == PETSC_TRUE stuff was removed years ago.
>
>
>  Barry
>
>
>
>
> Satish
>
> On Wed, 14 Jan 2009, Barry Smith wrote:
>
>
>  From the PETSc developers guide
>
> Do not use {\em if (rank == 0)} or {\em if (v == PETSC\_NULL)} or  
> {\em if (flg
> == PETSC\_TRUE)} or {\em if (flg == PETSC\_FALSE)}
> instead use {\em if (!rank)} or {\em if (!v)} or {\em if (flg)} or  
> {\em if
> (!flg)}.
>
> There was a flag == PETSC_TRUE in PETSc 3.0.0 that wasted a lot of  
> several
> peoples time finding it. Come on folks, we have better things to do  
> with our
> time. Please avoid this incorrect usage.
>
>  Barry
>
>
>
>
>
>
> -- 
> What most experimenters take for granted before they begin their  
> experiments is infinitely more interesting than any results to which  
> their experiments lead.
> -- Norbert Wiener




More information about the petsc-dev mailing list