Peeter Joot's (OLD) Blog.

Math, physics, perl, and programming obscurity.

On C operator precedence.

Posted by peeterjoot on September 23, 2011

Saw the following code fragment today, illustrating a common precedence mistake:

         if ( ( ( A == type ) || ( B == type ) )
              && ( ( 0 == p->size1 ) && ( 0 == p->size2 ) ) ||
                 ( p->size1 < p->size2 ) )

This has the following structure

if ( typeMatches && isZero || isLess )

but should be:

if ( typeMatches && (isZero || isLess) )

This doesn’t behave in an expected fashion, which can be verified easily:

#include <stdio.h>

int main()
{
   for ( unsigned typeMatches = 0 ; typeMatches < 2 ; typeMatches++ )
   {
      for ( unsigned zero = 0 ; zero < 2 ; zero++ )
      {
         for ( unsigned less = 0 ; less < 2 ; less++ )
         {
            unsigned r = typeMatches && zero || less ;

            printf("typeMatches: %u; zero: %u; less: %u\t:%u\n", typeMatches, zero, less, r ) ;
         }
      }
   }

   return 0 ;
}

I’ve seen people argue vehemently that you need to memorize the whole C operator precedence table to avoid errors like this. I think my preference is to prefer simple code. My head hurt when I looked at this fragment. Wouldn’t it be easier to understand what the author was thinking if some temporary variables were used. Perhaps like so:


            if ( ( A == type ) || ( B == type ) )
            {
               bool foundZero = ( 0 == p->size1 ) && ( 0 == p->size2 ) ;
               bool foundLess = ( p->size1 < p->size2 ) ;

               if ( foundZero || foundLess )
               {
                  // ...
               }
            }

I like variable names (and these could be more specific) used to implicitly comment the code. I think I’d seen that suggestion, and the suggestion not to let a statement span multiple lines, years ago one of Code Complete, or The Pragmatic programmer. Both of those are great books that deserve a read by any programmer (I’m due for a more recent re-read myself).

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: