Mailing List Archive


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: argc loop [tlug]



Steven and I each saw each other's flaws, but failed to see our own. 
Together, we fix each other's code. Release early, release often! 
That's the bazaar. 

Well Steven, what have I missed this time? 

First my bug. Earlier I wrote: 

> Also tolerable, but less readable, would be: 
> 
>     while (*argv++!=(char *)0)

As Stephen alluded, it has a bug, of incrementing argv too early 
and hence skipping over the first argument. Also, when argc>0, 
it requires the inside of the loop to test for *argv==NULL 
to avoid deferencing a null pointer the last time through the 
loop. This reminds me of the guide "Don't stop at the first bug.". 
A fix would be: 

   for ( ;*argv!=(char *)0);argv++)
or
   for ( ;*argv!=NULL;argv++)

My bug is a good example of why one should strive for 
readability first. 

----------------------------------------------------------------

Stephen wrote:

> Jim writes:

>  > while the latter code requires another test inside the loop 
>  > to avoid dereferencing a null pointer. 
> 
> Not in my environment (PPC Mac OS X 10.4.9).

Don't be so parochial. 

Strive for portability instead. 

The world of C is bigger than the PPC Mac OS X 10.4.9 environment. 
C is now used in a wide variety of environments, far beyond its roots. 
The standards have grown to embrace that variety. 
There are standards compliant environments for which argc is 
legitimately zero, so it's better to avoid assuming argc>0. 

Portability is a good thing. 
Adopt code patterns that are more portable. 
Make it a habit. 

So 

   do { ... } while (*argv++ != NULL);

is deprecated. 

Let's put the "Don't stop at the first bug." guideline into practice. 

>  > while the latter code requires another test inside the loop 
>  > to avoid dereferencing a null pointer. 
> 
> Not in my environment (PPC Mac OS X 10.4.9).

Don't be so sure. 

Even for typical parsing (i.e., when argc>0), the last pass through 
the do-while loop has to test for *argv==NULL, to avoid dereferencing 
a null pointer. So the do-while loop is not just deprecated. 
We both fell for very similar bugs. 
I'm surprised I did not spot that earlier. 
I was so focused on argc==0, that I was blind. 

Tenure's a wonderful thing, eh? 

----------------------------------------------------------------

This just reinforces my preference for 

   for (i=0;i<argc;i++)

for being so straightforward and easy to read, 
over any of the code that increments argv. 

----------------------------------------------------------------

Here's some code for y'all to play with: 

#include <stdlib.h>
#include <stdio.h>

int main(int argc,char *argv[])
{
#if 0
   int i;

   for (i=0;i<argc;i++)
      printf("%s\n",argv[i]);
#endif
#if 0
   while (*argv++!=NULL) {
      int c;

      printf("%s\n",*argv);
      c=**argv; /* to provoke dereferencing null pointer */
      if (c!='\0')
         printf("%c\n",c);
   }
#endif
#if 0
   for ( ;*argv!=NULL;argv++)
      printf("%s\n",*argv);
#endif
#if 0
   do {
      int c;

      printf("%s\n",*argv);
      c=**argv; /* to provoke dereferencing null pointer */
      if (c!='\0')
         printf("%c\n",c);
   } while (*argv++ != NULL);
#endif
#if 0
   do {
      printf("%08lX\n",*argv); /* highly non-portable code */
   } while (*argv++ != NULL);
#endif

   exit(EXIT_SUCCESS);
}



Home | Main Index | Thread Index

Home Page Mailing List Linux and Japan TLUG Members Links