diff options
author | Tobias Klauser <tklauser@distanz.ch> | 2008-01-27 11:37:44 +0100 |
---|---|---|
committer | Tobias Klauser <tklauser@xenon.tklauser.home> | 2008-01-27 11:37:44 +0100 |
commit | 7e0f021a9aec35fd8e6725e87e3313b101d26f5e (patch) | |
tree | b1cacc4b24393f517aeb4610e9e1021f954307a8 /reference/C/CONTRIB/SAWTELL/c-lesson.6 |
Initial import (2.0.2-6)2.0.2-6
Diffstat (limited to 'reference/C/CONTRIB/SAWTELL/c-lesson.6')
-rwxr-xr-x | reference/C/CONTRIB/SAWTELL/c-lesson.6 | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.6 b/reference/C/CONTRIB/SAWTELL/c-lesson.6 new file mode 100755 index 0000000..67f8852 --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/c-lesson.6 @@ -0,0 +1,331 @@ + + Lesson 5. + + The Pre-processor and Header Files. + +The pre-processor is activated by a '#' character in column one of the source +code. There are several statements vis: + +#include + +#define +#undef + +#if +#else +#endif + +#ifdef +#ifndef + +#pragma + + #include. + + In the programming examples presented in the previous lessons you will +probably have noticed that there is this statement: + +#include <stdio.h> + +right at the start of the program text. This statement tells the pre-processor +to include the named file in the your program text. As far as the compiler is +concerned this text appears just as if you had typed it yourself! + + This is one of the more useful facilities provided by the 'C' language. +The #include statement is frequently combined with the #if construct. +In this program fragment the file "true.h" is included in your program +if the pre-processor symbol FLAG is true, and "false.h" included if FLAG +is false. + +#if ( FLAG ) +# include "true.h" +#else +# include "false.h" +#endif + +This mechanism has many uses, one of which is to provide +portability between all the 57,000 slightly different versions of unix and also +other operating systems. Another use is to be able to alter the way in which +your program behaves according to the preference of the user. + +Of course, you will be asking the question "Where is the file stored?". +Well, if the filename is delimited by the "<" and ">" characters as in the +example above the file comes from the /usr/include directory, but if the name +of the file is delimited by quotes then the file is to be found in your current +working directory. (This is not quite the whole truth as 'C' compilers allow +you to extend the search path for the include files using command line option +switches. - See your compiler manual for the whole story. ) + +So, I would like to suggest that you to have a look around the /usr/include +directory and its /sys sub-directory. You should use either your editor +in 'view' mode or the pg utility. This will ensure that you can't have an +accident and alter one of the files by mistake if you are slightly silly +and just happen to be logged on as the super-user. + +A typical file to examine is usr/include/time.h. + +It's quite small so here it is. + +/* Copyright (c) 1984 AT&T */ +/* All Rights Reserved */ + +/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ +/* The copyright notice above does not evidence any */ +/* actual or intended publication of such source code. */ + +#ident "@(#)/usr/include/time.h.sl 1.5 4.2 04/20/87 18195 AT&T-SF" +/* 3.0 SID # 1.2 */ +struct tm { /* see ctime(3) */ + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; +extern struct tm *gmtime(), *localtime(); +extern char *ctime(), *asctime(); +int cftime(), ascftime(); +extern void tzset(); +extern long timezone, altzone; +extern int daylight; +extern char *tzname[]; + + As you can see ( forgetting about the comments and #ident ) there are three +different uses for the file. + + a) The definition of data structures and types. + b) The declaration of functions which use the data structures. + c) The declaration of of external data objects. + + These lines of code are all you need in your program in order to be able to +use, in this case, the library routine to access the clock in the computer, +but of course the paradigm applies to all programs which are created by one +programmer and used by another member of the programming team. Note that, by +proxy, or whatever, the author of the library routines has in effect become +a member of your programming team. + + You might care to write a program or two which use this header file, +and for those who are motivated it might be an idea to re-implement localtime +so that it understands Summer Time in the Southern Hemisphere. (!) + +Using another totally trivial example in order to get the idea across please +examine the hello world program printed immediately below. + +/* ------------------------------------------------------------ */ + +#ident "@(#) hw_uc.h UPPER CASE version." + +#define HELLO_MESSAGE "HELLO WORLD...\n"; + +/* ------------------------------------------------------------ */ + +#ident "@(#) Hello World" + +#include <stdio.h> +#include HW_H + +#if !defined( HELLO_MESSAGE ) +# error "You have forgotten to define the header file name." +#endif + +char *format = "%s", + *hello = HELLO_MESSAGE; + +main() +{ + printf ( format, hello ); + } + +/* ------------------------------------------------------------ */ + +You will no doubt notice that the symbol HW_H is used instead of a header file +name. This gives us the ability to force the inclusion of any file we wish by +defining the symbol HW_H to be the desired file name. It can be done like this: + +cc -DHW_H="\"hw_uc.h\"" hello.c + +The compiler output is placed, by default, in the file a.out, so to execute it +issue the command: + +a.out + +Which, fairly obviously, produces the output: + +HELLO WORLD... + +As we are going to generate another version of the program we had better move +the executable image file to another file name: + +mv a.out hello_uc + +Now to produce the other version issue the command line: + +cc -DHW_H="\"hw_lc.h\"" hello.c; mv a.out hello_lc; hello_lc + +Which compiles the other version of the hello.c program, using this version of +the include file: + +/* ------------------------------------------------------------ */ +#ident "@(#) hw_lc.h Lower Case version." + +#define HELLO_MESSAGE "Hello World...\n"; +/* ------------------------------------------------------------ */ + +and then moves the executable image to a different file and executes it. +Note that more than one command per line can be issued to the shell by +separating the commands with the ';' delimiting character. +Here - Surprise, Surprise - is the output of the second version. + +Hello World... + +I'd like to suggest that you use your editor to cut these example programs +and the shell file below out of the mail file and have a play with them. + +/* ----------------------------------------- */ + +# @(#) Shell file to do the compilations. + +cc -o hello_uc -DHW_H="\"hw_uc.h\"" hello.c +cc -o hello_lc -DHW_H="\"hw_lc.h\"" hello.c + +/* ----------------------------------------- */ + + +#define + + This statement allows you to set up macro definitions. The word immediately +after the #define, together with its arguments, is expanded in the program +text to the whole of the rest of the line. + +#define min(a, b) ((a<b) ? a : b ) + + Some things to note: + + 1) There isn't a space between the last character of the symbol being defined + and the opening parenthesis enclosing the arguments, and there MUST NOT BE + one. + + 2) The code into which the macro is expanded MUST always be enclosed in + parentheses and for safety always use parentheses to get the arithmetic + right. + + 3) Never EVER define a macro, and use it with a side effect. e.g. + + c = min ( a++, b); /* DON'T _EVER_ DO THIS!!! */ + + Do you think that the value of 'a' will get advanced after the + macro is used? Well it WON'T. It gets incremented after the less + than test and before the values get assigned! I have written a tiny + program which uses the min macro above. Have a look at the output + from the pre-processor. Lesson One told you how to do this. + Now execute it and get an educative surprise! + +/* ----------------------------------------- */ + +#include <stdio.h> +#define min(a, b) ((a<b) ? a : b ) + +main() +{ int a,b,c; + + a = 1; + b = 2; + c = min ( a++, b); /* DON'T _EVER_ DO THIS!!! */ + printf ( "a: %d, b: %d, c: %d\n", a, b, c ); + } + +/* ----------------------------------------- */ + + 4) You can continue a macro on the next line by putting a \ ( back-slash ) + as THE VERY LAST character on the line. NOTHING, not even a space may + follow, as your compiler just can't handle it. I spent far too long trying + to find one of those really difficult bugs, and it turned out that this + was the problem - spaces are transparent aren't they? + + 5) Using macros is fast and convenient, but they do take up a lot of memory + because the code is expanded and inserted into the output stream for + every occurrence of the macro in your code. There is a trade-off between + using a macro and a function. + + The symbol does not have to be the handle for a macro expansion, but can just +be equated to a single constant. This is done many times over in the header +files provided by the operating system vendor. Have a look in +/usr/include/sys/file.h for an example of this. + +#undef + + Not surprisingly this preprocessor command removes a symbol WHICH IS BEING + USED BY THE PRE-PROCESSOR - don't confuse it with compiler proper symbols. + + Note that the symbol can be a macro name, in which case the space + used for the code expansion is made available for re-use. + +#if ( FLAG ) + + /* Code in here is sent on to the compiler if FLAG is true. */ + +#else + + /* Code in here is sent on to the compiler if FLAG is false. */ + +#endif + + When the pre-processor encounters one of these, the lines of code between the +#if and the corresponding #else or #endif are either skipped over or allowed to +proceed to the compilation phase depending on the truth or falsity of the +logical expression ( FLAG ). All the logical and boolean expressions available +as part of the 'C' language are available here. You are also allowed to say: + +#if defined( FLAG ) or, +#if !defined( FLAG ) + + + The symbol FLAG may be an expression which reduces to a boolean value. + + A convention which is adhered to quite well is that all pre-processor +symbols are in UPPER_CASE so as to make them obvious. + +#ifdef FLAG or, +#ifndef FLAG + + These two statements are the old fashioned way of testing whether a symbol is +defined or not. They are absolutely the same as the previous example. + + There are two more pre-processor statements, namely the #pragma and +the "stringizing" operator. The #pragma is used to alter the way in which +the compiler works on a block of code, but it is completely implementation +dependant and you must refer to your compiler manual. I can't help as +they are all different. The "stringizing" operator is quite an advanced +technique and will be dealt with later on. + +Copyright notice:- + +(c) 1993 Christopher Sawtell. + +I assert the right to be known as the author, and owner of the +intellectual property rights of all the files in this material, +except for the quoted examples which have their individual +copyright notices. Permission is granted for onward copying, +but not modification, of this course and its use for personal +study only, provided all the copyright notices are left in the +text and are printed in full on any subsequent paper reproduction. + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ |