Topic : Programming In C
Author : Brian Kernighan
Page : << Previous 7  Next >>
Go to page :


it two string names as arguments, then pro-
ceeded to clobber both of them by  incrementation.   So  how
come we don't lose the original strings in the function that
called strcopy?

     As we said before, C is a ``call by  value''  language:
when  you  make a function call like f(x), the VALUE of x is
passed, not its address.  So there's no way to ALTER x  from
inside  f.  If x is an array (char x[10]) this isn't a prob-
lem, because x IS an address anyway, and you're  not  trying
to  change  it, just what it addresses.  This is why strcopy
works as it does.  And it's convenient not to have to  worry
about making temporary copies of the input arguments.

     But what if x is a scalar and you do want to change it?
In  that  case,  you have to pass the ADDRESS of x to f, and
then use it as a pointer.  Thus for example, to  interchange
two integers, we must write

     flip(x, y)
        int *x, *y; {
             int temp;
             temp = *x;
             *x = *y;
             *y = temp;
     }


and to call flip, we have to pass the addresses of the vari-
ables:

     flip (&a, &b);


18. Multiple Levels of Pointers; Program Arguments


     When a C program is called, the arguments on  the  com-
mand line are made available to the main program as an argu-
ment count argc and an array of character strings argv  con-
taining  the arguments.  Manipulating these arguments is one
of the most common  uses  of  multiple  levels  of  pointers
(``pointer  to  pointer  to  ...'').  By convention, argc is
greater than zero; the first argument (in  argv[0])  is  the
command name itself.

     Here is a program that simply echoes its arguments.

     main(argc, argv)
        int argc;
        char **argv; {
             int i;
             for( i=1; i < argc; i++ )
     }


Step by step: main is called with two arguments,  the  argu-
ment count and the array of arguments.  argv is a pointer to
an array, whose individual elements are pointers  to  arrays
of  characters.  The zeroth argument is the name of the com-
mand itself, so we start to print with the  first  argument,
until  we've  printed them all.  Each argv[i] is a character
array, so we use a `%s' in the printf.

     You will sometimes see the declaration of argv  written
as

     char *argv[ ];

which is equivalent.  But we can't  use  char  argv[  ][  ],
because  both  dimensions are variable and there would be no
way to figure out how big the array is.

     Here's a bigger example using argc and argv.  A  common
convention  in  C  programs is that if the first argument is
`-', it indicates a flag of some sort.  For example, suppose
we want a program to be callable as

     prog -abc arg1 arg2 ...

where the `-' argument is optional; if it is present, it may
be followed by any combination of a, b, and c.

     main(argc, argv)
        int argc;
        char **argv; {
             ...
             aflag = bflag = cflag  = 0;
             if( argc > 1 && argv[1][0] == '-' ) {
                     for( i=1; (c=argv[1][i]) != '\0'; i++ )
                             if( c=='a' )
                                     aflag++;
                             else if( c=='b' )
                                     bflag++;
                             else if( c=='c' )
                                     cflag++;
                             else
                                     printf("%c?\n", c);
                     --argc;
                     ++argv;
             }

             ...


     There are several  things  worth  noticing  about  this
code.   First,  there  is  a real need for the left-to-right
evaluation that &&  provides;  we  don't  want  to  look  at
argv[1] unless we know it's there.  Second, the statements

             --argc;
             ++argv;


let us march along the argument list by one position, so  we
can skip over the flag argument as if it had never existed _
the rest of the program is independent  of  whether  or  not
there  was a flag argument.  This only works because argv is
a pointer which can be incremented.

19. The Switch Statement; Break; Continue


     The switch statement can be used to replace the  multi-
way  test  we  used in the last example.  When the tests are
like this:

     if( c == 'a' ) ...
     else if( c == 'b' ) ...
     else if( c == 'c' ) ...
     else ...


testing a value against a series of  constants,  the  switch
statement  is  often  clearer and usually gives better code.
Use it like this:

     switch( c ) {

     case 'a':
             aflag++;
             break;
     case 'b':
             bflag++;
             break;
     case 'c':
             cflag++;
             break;
     default:
             printf("%c?\n", c);
          


Page : << Previous 7  Next >>