the compilation process
play

The Compilation Process Preprocessing: o processes include-files, - PDF document

4/1/14 The Compilation Process Preprocessing: o processes include-files, conditional compilation and macros. Compilation: Writing Large Programs o takes the output of the preprocessor and the source code, and generates assembler


  1. 4/1/14 ¡ The Compilation Process • Preprocessing: o processes include-files, conditional compilation and macros. • Compilation: Writing Large Programs o takes the output of the preprocessor and the source code, and generates assembler source code, i.e., making .s file. • Assembly: o takes the assembly source code and produces an assembly Based on slides from K. N. King and Dianna Xu listing with offsets. The assembler output is stored in an object file, i.e., .o file. • Linking: Bryn Mawr College o takes one or more object files or libraries as input and CS246 Programming Paradigm combines them to produce a single (usually executable) file. Compilation Compiler/Assembler and Linker • Compile green.o: cc –c green.c • Compile blue.o: cc –c blue.c • Link together: cc green.o blue.o Multiple Source Files Header Files • How can a function in one file call a function • The decision to divide your program into multiple source files is not only a matter of size. that ’ s defined in another file? • One and only one .c file must contain a main . • How can a function access an external variable in another file? • Functions that handle some common aspects of a program should be grouped into the same file. • How can two files share the same macro definition or type definition? • main, data structure implementation (i.e. linked list), I/O, utilities, display/GUI, etc • The #include directive tells the preprocessor to insert the contents of a specified file. 1 ¡

  2. 4/1/14 ¡ Sharing Function Prototypes The #include Directive • To share a function among files, we put its • The #include directive has two primary forms. definition in one source file, then put declarations • For C ’ s own library: in other files that need to call the function. o #include < filename > : Search the directory (or • If a function is to be called in more than one file, directories) in which system header files reside. put its prototype into a .h . • For all other header files: • Always include the .h with f ’ s prototype in o #include " filename " : Search the current the .c that contains f ’ s definition. directory, then search the directory (or directories) in which system header files reside. o For any .c , always include your own .h . • The difference between the two has to do with how • A header file should never contain function the compiler locates the header file. definitions. The #include Directive The #include Directive • Don ’ t use brackets when including header files • The file name in an #include directive may that you have written: include information that helps locate the file, such as a directory path or drive specifier: #include <myheader.h> /*** WRONG ***/ • The preprocessor will probably look for #include "c:\cprogs\utils.h" /* Windows path */ myheader.h where the system header files are kept. #include "/cprogs/utils.h" /* UNIX path */ • Although the quotation marks in the #include directive make file names look like string literals, the preprocessor doesn ’ t treat them that way. The #include Directive Sharing Variables • It ’ s usually best not to include path or drive • Variables shared between files are defined in one information in #include directives. file, and declared in all files that need to access it. • Bad examples of Windows #include directives: o Definition of a variable causes the compiler to set memory aside #include "d:utils.h" • extern #include "\cprogs\include\utils.h" #include "d:\cprogs\include\utils.h" o extern int i, a[]; • Better versions: o extern informs the compiler that the variables i and #include "utils.h" a are defined elsewhere. #include "..\include\utils.h" 2 ¡

  3. 4/1/14 ¡ extern variables Example: Arithmetic Expression Infix notation: • extern declarations often go in to a header file. • Operators are written between the operands they act on; • The variable must have one (and only one) definition among all files. e.g., “2+2”. o int x; • Parentheses surrounding groups of operands and • Any file that wishes to access a variable that is defined in operators are used to indicate the intended order in another file must declare such a variable as extern which operations are to be performed. o extern int x; • In the absence of parentheses, precedence rules • When we use extern in the declaration of an array, we determine the order of operations. can omit the length of the array: E.g., Because “-” has lower precedence than “*”, the infix extern int a[]; expression “3-4*5” is evaluated as “3-(4*5)”, not as • Since the compiler doesn ’ t allocate space for a at this “(3-4)*5”. If you want it to evaluate the second way, you time, there ’ s no need for it to know a ’ s length. need to parenthesize. Example: Arithmetic Expression Example: Arithmetic Expression Advantage of RPN: Postfix notation (a.k.a. Reverse Polish Notation (RPN)) The postfix notation obviates the need for parentheses that • Operators follow their operands, e.g., adding three are required by infix. and four is written as “3 4 +” rather than “3+4”. • With infix notation, “3-4*5” can be written as “3-(4*5)”, • If there are multiple operations, the operator is given that means something quite different from “(3-4)*5”. immediately after its second operand; so the • In postfix, the former is written as “3 4 5 * -”, which expression written “3 - 4 + 5” in infix notation unambiguously means “3 (4 5 *) -”, and the latter is written as “3 4 - 5 *”, which unambiguously means would be written “3 4 - 5 +” in RPN: first subtract 4 “(3 4 -) 5 *”. from 3, then add 5 to that. • Postfix notation is easier to parse by computer than infix notation, but many programming languages use infix due to its familiarity. Example: Arithmetic Expression Example (RPN) • How the expression 30 5 - 7 * : will be evaluated: • Interpreters of RPN are often stack-based. 1. Push 30 onto the stack. • General idea: 2. Push 5 onto the stack. o Operands are pushed onto a stack, and when an 3. Pop the top two numbers from the stack, subtract 5 operation is performed, its operands are popped from from 30, giving 25, and then push the result back a stack and its result pushed back on. onto the stack. o At the end, the value of the postfix expression is on 4. Push 7 onto the stack. the top of the stack. 5. Pop the top two numbers from the stack, multiply • Since all the needed stack operations take constant them, and then push the result back onto the stack. time, and the evaluation algorithm is quite simple, • The stack will now contain 175, the value of the RPN expressions can be evaluated quickly and easily. expression. 3 ¡

  4. 4/1/14 ¡ Example Program Structure • The implementation of a stack-based calculator: main.h #include <stdio.h> o 1 2 – 4 5 + * ==> (1-2) * (4+5) enum _bool {FALSE, TRUE} Bool; • Two globals: init.c main.c stack.c io.c #include "init.h" #include "stack.h" #include <stdlib.h> #include <ctype.h> o double s[MAX]; #include "main.h" #include "main.h" #incluce "init.h" #include "io.h" extern int sp; #include "io.h" #include "main.h “ o int sp = 0; void init() {} #include "stack.h" extern double s[]; void push(double d){} #include "main.h" Optype getop(char s[]){} double pop(){} • Stack related operations int sp = 0; double top(){} double s[MAX]; int isempty(){} int main () {} int isfull(){} • I/O operations stack.h #define MAX 100 init.h io.h void initstack(); void init(); #define MAXOP 100 void push(double d); typedef enum _optype {NUM='n', PLUS='+', MINUS='-', double pop(); MULT='*', DIV='/', NEWLINE='\n'} Optype; double top(); int isempty(); Optype getop(char s[]); int isfull(); main.c io.c int main() { int getop(char s[]) { Optype t; char str[MAXOP]; double d; int i=0; char c; init(); while ((s[0] = c = getchar()) == ' ' || c == '\t') ; while((t = getop(str)) != EOF) { switch(t) { s[1] = '\0'; case NUM: if (!isdigit(c) && c != '.') /* not a number */ push(atof(str)); break; case PLUS: return c; d=pop(); push(pop()-d); break; if (isdigit(c)) /* collect int part */ case MINUS: while(isdigit(s[++i] = c = getchar())) ; push(pop()-pop()); break; case NEWLINE: if (c == '.') /* collect fractional part */ printf("\t%.2f\n", pop()); break; while(isdigit(s[++i] = c = getchar())) ; default: s[i] = '\0'; fprintf(stderr, "Error, unknown command %s\n", str); break; } if (c != EOF) } ungetc(c, stdin); return 0; return NUM; } } Protecting Header Files Protecting Header Files • If a source file includes the same header file twice, • Including the same header file twice doesn ’ t compilation errors may result. always cause a compilation error. • If the file contains only macro definitions, function prototypes, and/or variable declarations, there file3.h won ’ t be any difficulty. #include “file3.h” #include “file3.h” • If the file contains a type definition, however, file1.h file2.h we ’ ll get a compilation error. #include “file1.h” #include “file2.h” prog.c • When prog.c is compiled, file3.h will be compiled twice. 4 ¡

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend