'&$%CSE 303:Concepts and Tools for Software DevelopmentHal PerkinsSpring 2008Lecture 12— C: The C Preprocessor; printf/scanfCSE303 Spring 2008, Lecture 12 1'&$%Where are WeTwo important “sublanguages” used a lot in C (almost every program)• The preprocessor: runs even before the compiler (hence the name)• printf/scanf: interpret certain strings funny at run-time– Really just a library thoughTwo lectures in one (preprocessor a bigger topic).CSE303 Spring 2008, Lecture 12 2'&$%The compilation picturegcc does all this for you• -E to only preprocess, put result on stdout (rare)• -c to stop with .o (common; for part of a program)CSE303 Spring 2008, Lecture 12 3'&$%More about multiple filesTypical usage:• Preprocessor #include to ge t a file describing code)• Linker is passed your .o and other code– By default, the “standard C library”– Other .o and .a filesWhole lecture on the linker and libraries later.CSE303 Spring 2008, Lecture 12 4'&$%The PreprocessrRewrites your .c file before the compiler gets at the code.• Lines starting with # tell it what to do.Can do c razy things (please don’t); uncrazy things are:1. Including contents of header files (see previous slide)2. Defining constants and parameterized macros(textual-replacements)• Actually token-based (to be explained)• Easy to misdefine and misuse3. Conditional compilation• Include/exclude part of a file• Example uses: code for debugging, c ode for som e c omputers,“the trick” for including header files only onceCSE303 Spring 2008, Lecture 12 5'&$%File inclusion#include <foo.h>• Search for file foo.h in “system include directories” (on attu/usr/include and s ubdirs) for foo.h and include itspreprocessed contents (recursion!) at this place.– Typically lots of nested includes, so result is a mess nobodylooks at.– Idea is simple: declaration for fgets is in stdio.h (use man forwhat file to include)• #include "foo.h" the same but first look in current directory.– How you break your program into sm aller files and still m akecalls to other files.• gcc -I dir1 -I dir2 ... look in these directories for allheader files first (ke eps paths out of your code files).CSE303 Spring 2008, Lecture 12 6'&$%ConventionsConventions to always follow:1. Give included file s names ending in .h; only include thes e headerfiles.2. Do not put functions in a header file; only struct definitions,prototypes, and other includes3. Do all your #include at the beginning of a file.4. For header file foo.h start it with:#ifndef FOO_H#define FOO_Hand e nd it with:#endif(We w ill learn why soon.)CSE303 Spring 2008, Lecture 12 7'&$%Simple macros#define M_PI 3.14 // capitals a convention to avoid problems#define DEBUG_LEVEL 1#define NULL 0 // already in standard libraryReplace all matching toke ns in the rest of the file• Knows w here “words” start and end (unlike sed)• Has no notion of scope (unlike C compiler)• (Rare: can shadow with another #define or use #undef)#define foo 17void f() {int food = foo; // becomes int food = 17 (ok)int foo = 9+foo+foo; // becomes int 17 = 9+17+17 (nonsense)}CSE303 Spring 2008, Lecture 12 8'&$%Macros with parameters#define TWICE_AWFUL(x) x*2#define TWICE_BAD(x) ((x)+(x))#define TWICE_OK(x) ((x)*2)double twice(double x) { return x+x; } // my preferenceReplace all matching “calls” with “body” but with text of argumentswhere the formals are.Gotchas (understand why!):• y=3; z=4; w=TWICE_AWFUL(y+z);• y=7; z=TWICE_BAD(++y); z=TWICE_BAD(y++);Common misperception: Macros a good idea to avoid performanceoverhead of a function call.Macros can be more flexible though (TWICE_OK works on ints anddoubles without conversions (which could round))CSE303 Spring 2008, Lecture 12 9'&$%Justifiable usesParameterized macros are generally to be avoided (use functions), butthere are things functions cannot do:#define NEW_T(t,cnt) ((t*)malloc((cnt)*sizeof(t))#define PRINT(x) printf("%s:%d %s\n",__FILE__,__LINE__,x)CSE303 Spring 2008, Lecture 12 10'&$%Conditional compilation#ifdef FOO (matching #endif later in file)#ifndef FOO (matching #endif later in file)#if FOO > 2 (matching #endif later in file)(You can alse have a #else inbetween somewhere.)Simple use:#ifdef DEBUG // do following only when debuggingprintf(...);#endifFancier:#ifdef DEBUG // use DBG_PRINT for debugging-prints#define DBG_PRINT(x) printf("%s",x)#else#define DBG_PRINT(x) // replace with nothing#endifNote: gcc -D FOO makes FOO “defined”CSE303 Spring 2008, Lecture 12 11'&$%Back to header filesNow we know what this means:#ifndef SOME_HEADER_H#define SOME_HEADER_H... rest of some_header.h ...#endifAssuming nobody else defines SOME_HEADER_H (convention), the first#include "some_header.h" will do the define and include the restof the file, but the second will skip everything.• More efficie nt than copying the prototypes over and over again.• In presence of c ircular includes, necessary to avoid “creating” aninfinitely large result of preproce ss ing.So we always do this.CSE303 Spring 2008, Lecture 12 12'&$%C preprocessor summaryA few easy to abuse features and a bunch of conventions (forovercoming C’s limitations).• #include (cycles fine with “the trick”, the way you say whatother definitions you need)• #define (avoids magic constants, paramet erized macros have afew justifiable uses, toke n-based tex t replacem ent)• #if... (for showing the compiler less code)CSE303 Spring 2008, Lecture 12 13'&$%printf and scanf“Just” two library functions in the standard library• Prototypes in stdio.hExample: printf("%s: %d %g ", x, y+9, 3.0)They can take any number of arguments.• You can define functions like that too, but it is rarely useful,arguments are not checked for any types, and writing the functiondefinition is a pain.– Not covered in 303.The f is for “format” – crazy characters in the format string controlformatting.CSE303 Spring 2008, Lecture 12 14'&$%The rulesTo avoid HYCSBWK:• Number of arguments better m atch number of %• Corresponding arguments better have the right types (%d,int%f,float, %e,float (prints scientific), %s,\0-terminated char*, ...(look them up))For scanf, arguments should be pointers to the right type of thing(reads input and assigns to the variables).• So int* for %d, but still char* for %s (not char**)CSE303 Spring 2008, Lecture 12 15'&$%More funny charactersBetween the % and the letter (e.g., d) c an be ot her things that controlformatting (look the m
View Full Document