ansi C


if you are concerned about strict adherence to the ISO C standard, you should use the -ansi option when you compile your programs with the gcc


  • ADT
  • refs
  • strings

  • advices

    dont use global variables! never-ever!

    use macro #define for that

    #include <stdio.h>
    
    #define MAX_VALUE 100    /* global but not variable ! */
    
    int
    main (int argc, char** argv, char** envp)
    {
      printf ("%i\n", MAX_VALUE) ;
      return 0 ;
    }
    

    if you need the state - use static variable in function

    #include <stdio.h>
    
    void
    myfAunc (void) ;
    
    int
    main (int argc, char** argv, char** envp)
    {
      myfAunc () ;
      myfAunc () ;
      myfAunc () ;
      return 0 ;
    }    
    
    void
    myfAunc ()
    {
      static count = 0 ;
      printf ("%i\n", count++) ;
    }
    

    always use heading file as interface to your module(s)

    interface - file ifcace.h :

    #define MAX 100
    #define VAL 12.8
    
    enum { RED = 1 , GREEN = 2 , YELLOW = 7 } ;
    
    int    myfunc1 (int) ;
    double myfunc2 (double) ;
    

    implementation - file module1.c :

    int myfunc1 (int x)
    {
      return x + 2 ;
    }
        

    implementation - file module2.c :

    double myfunc2 (double x)
    {
      return x * 2 ;
    }
    

    main program - file main.c :

    #include 
    #include "iface.h"
    
    int main (int argc, char** argv, char** envp)
    {
    
      double x = myfunc2 (VAL + GREEN) ;
      printf ("%7.2f\n", (x + (double) myfunc1 (MAX)) ) ;
      return 0 ;
      
    }
    
     /* gcc -Wall module1.c module2.c main.c  */
    


    ADT

    one very simple way: enum. for exampe :

    enum { RED = 1 , GREEN = 2 , YELLOW = 7 } ;
    

    and two more complicated ways : stuct and union. for example :

    #include <stdio.h>
    #include <stdlib.h>
    
    /*     product type      */
    typedef struct 
    {
      int       num ;
      double    factor ;
      char*     name ;
      int       rate[10] ;
    } XSTRUCT ;
    
    /*      sum type       */
    typedef union 
    {
      int              num ;
      char             sign ;
    } YUNION ;
    
    int
    main (int argc, char* argv, char* envp)
    {
      YUNION  z ;
      XSTRUCT k ;
    
      scanf  ("%i",    &(z.num)) ;
      printf ("%i\n",  z.num) ;
      
      return 0 ;
    }
    

    ADT can be nested! for example:

    typedef union
    {
      char*           description ;
      int             identifyer  ;
    } Sum ;
    
    typedef struct 
    {
       char*          name ;
       int            age ;
       float          salary ;
       Sum            record ;
    } Product ;
    
    typedef union
    {
      int             num ;
      Product         data ;
    } Complex ;
    
    int
    main (int arc, char** argv, char** env)
    {
      return 0 ;
    }
    

    refs

    C87 has no "pass-by-reference" functionality. & means "addressof" and is a way to formulate a pointer from a variable. however, consider this:

    void func (int* x) { *x = 4; }
    
    void callfunc () { int x = 7 ; func (&x) ; }
    
    you're passing the value of the address of the local variable 'x' to 'func' as a pointer argument. a pointer is a memory address containing another memory address. underneath a reference to object is typically the machine address of the object - attach gdb to a process and you'll be able to see this

    what happens if you assign to a reference?

    you change the state of the referent ('referent' is the object to which the reference refers)

    what happens if you return a reference?

    the function call can appear on the left hand side of an assignment operator


    strings

    a notorious source of program bugs is trying to put more characters in a string than fit in its allocated size. when writing code that extends strings or moves characters into a pre-allocated array, you should be very careful to keep track of the length of the text and make explicit checks for overflowing the array. many of the library functions do not do this for you! remember also that you need to allocate an extra byte to hold the null character that marks the end of the string

    parsing with strtok

    it's fairly common for programs to have a need to do some simple kinds of lexical analysis and parsing, such as splitting a command string up into tokens. you can do this with the strtok function, declared in the header file string.h

             char * strtok (char *restrict newstring, const char *restrict delimiters)  

    a string can be split into tokens by making a series of calls to the function strtok. the string to be split up is passed as the 'newstring' argument on the first call only. the strtok function uses this to set up some internal state information. subsequent calls to get additional tokens from the same string are indicated by passing a null pointer as the newstring argument. calling strtok with another non-null newstring argument reinitializes the state information

    the 'delimiters' argument is a string that specifies a set of delimiters that may surround the token being extracted. all the initial characters that are members of this set are discarded. the first character that is not a member of this set of delimiters marks the beginning of the next token. the end of the token is found by looking for the next character that is a member of the delimiter set. this character in the original string newstring is overwritten by a null character, and the pointer to the beginning of the token in newstring is returned. on the next call to strtok, the searching begins at the next character beyond the one that marked the end of the previous token. note that the set of delimiters do not have to be the same on every call in a series of calls to strtok

    if the end of the string newstring is reached, or if the remainder of string consists only of delimiter characters, strtok returns a null pointer