UMBC CMSC201, Computer Science I, Fall 1994
     Sections 0101, 0102 and Honors 
 Thursday November 3, 1994 
 Assigned Reading: 9.2 - 9.3
 Handouts (available on-line): none
 Topics Covered:
   -   We are running a bit behind the posted syllabus.  We
     will continue developing our random number library.  We want
     to allow our client to set the range of numbers that
     GetRandomNumber() would produce.  Instead of passing,
     extra parameters to GetRandomNumber() we will use
     a new feature of C called global variables.  We traced
     through a program that 
     illustrates the lexical scoping of global and local variables
     in C.
   
-  Then we wrote a new version of our
     program which has a SetRandomRange function.
     The output of the program is
     still the same as the previous version.
   
-  We broke up our program into three pieces:
    the header file,
    the implementation of
    the functions, and the main
    program.  These programs can be compiled separately, and
    we can put the implemented functions in a library.
    See sample run.
  
-  It turns out that the rand() function that we
    used is not very good, because the lower digits of the
    generated numbers are predictable.  Since we used the
    modulo operator to reduce the range of the random number,
    this means the random numbers we generated may be quite
    predictable.  Again, we consulted the
    manual pages of a different
    random number generator.  According to the manual the
    random() function produces numbers where every digit
    appears to be random.
  
-   We incorporated the random() and srandom()
    functions into a new
    implementation of our random number library.  This new
    library can be linked to our main program without changing or
    recompiling the main program because the interface between
    these two parts remains the same.  (See
    sample run.)
  
-  We moved on to explain what the preprocessor directive
     
       #ifndef
     really means.  We looked at a 
     program where the
     constant MARKER was defined; and a 
     program where the
     constant was not defined.  The compiled programs run differently,
     but it is important to note that in each case the C preprocessor
     stripped a printf statement from the file before passing
     the file to the C compiler.
-  The purpose of the C preprocessor is to take care of the
     preprocessor directives, such as
     #include, #define and #ifndef,
     before the "real" C compiler looks at the file.  The preprocessor
     usually strips the comments from the source file and replaces
     every occurrence of the constants with their definitions. 
     We looked at a sample program
     and the output from the
     preprocessor.
  
-  We also looked at what happens when a 
     program includes a
     header file.
     The output from the preprocessor
     has a copy of the header file in the middle of the main program.
  
-  In our second example,
     the main program includes both the header.h file and
     a second header file.
     The second header file also includes header.h, so the
     output from the preprocessor
     contains two copies of header.h.  This is bad because
     the global variable global_variable is initialized twice,
     which would result in a syntax error.
  
-  The solution to this problem is to realize that we can
     use the #ifndef directive to make sure that the
     same header file we not be given to the C compiler twice.
     The C preprocessor will remove one of the copies.
     For example, in this program
     the constant MARKER is defined, so the first printf
     statement is not part of the 
     output from the preprocessor.
     In the second program, the
     constant MARKER is not defined, so the second printf
     statement is not part of the
     output from the preprocessor.
  
-   Thus, we can write the new header files:
   new_header.h and
   new_header2.h.
   When new_header.h is read the first time, the constant
   _new_header_h is not defined, so all of the file is
   included.  Also, the constant _new_header_h is defined when
   the file
   new_header.h is read the first time. If new_header.h 
   is included a second time, the constant _new_header_h would be 
   defined, so the body of the file would be stripped by the #ifndef
   directive.  As a result, when we give our new
   main program to the C
   preprocessor, the output from
   the preprocessor only has one copy of the body of
   new_header.h.
Last Modified: September 7, 1994
Richard Chang, chang@gl.umbc.edu