1 / 24

Preprocessor Directives

Preprocessor Directives. Phases of “compilation”. preprocess. compile. assemble. File1.c. File1.i. File1.s. File1.o. preprocess. compile. assemble. File2.c. File2.i. File2.s. File2.o. link. a.out. Preprocessor. The preprocessor performs tasks such as comment stripping

maryhorton
Download Presentation

Preprocessor Directives

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Preprocessor Directives CST 494/598 -- Gannod

  2. Phases of “compilation” preprocess compile assemble File1.c File1.i File1.s File1.o preprocess compile assemble File2.c File2.i File2.s File2.o link a.out Harry Koehnemann, Computing Studies

  3. Preprocessor • The preprocessor performs tasks such as • comment stripping • macro expansion • File inclusion • conditional compilation • In-line assembly • The preprocessor is controlled by directives which are not part of the C language proper. • Each directive begins with a # character and is written on a line by itself (use \ for line continuation). Harry Koehnemann, Computing Studies

  4. Macro Processing • Motivations for using macros: • save time (define a macro for a sequences we repeat many times) • clarify the meaning of the software (give a symbolic name to a cryptic sequence) • make the software easy to change (changing the macro definition, automatically updates the entire program) Harry Koehnemann, Computing Studies

  5. Macro Processing cont… • A macro is specified by: #define name replacementText • The preprocessor replaces each occurrence of name (except in string constants and character constants) in the source text with replacementText • Very efficient – no function call made • Caution - textual substitutions are inherently unsafe Harry Koehnemann, Computing Studies

  6. Object-like macros • Object-like macros -- the most common use of #define directives is to give meaningful names to constants (manifest constants) • #define PI 3.14 • #define BUFFER_SIZE 1024 • Substitutions are not made within quoted strings • If a macro contains its own name, either directly or via intermediate macros, it is not expanded again when the expansion is examined for more macros. • #define foo (4 + foo) • Why do we need the parenthesis? What is value w/ out parens? • x = foo * 10; Harry Koehnemann, Computing Studies

  7. Function-like macros • Function-like macros look just like function calls • To define a function-like macro put () RIGHT after the macro name. E.g, #define init() struct timeval t; \ gettimeofday( &t, NULL ); \ srand48( t.tv_sec ); • Functions can have arguments #define min(X, Y) ((X) < (Y) ? (X) : (Y)) Harry Koehnemann, Computing Studies

  8. Parameters • If a parameter name is preceded by a #, it will be expanded into a quoted string (stringification). #define dprint(expr) \ printf(#expr “ = %g\n”, expr) • Arguments can be concatenated using the ## operator #define paste(front, back) front ## back Harry Koehnemann, Computing Studies

  9. Swallowing the semicolon • How does the following get expanded? #include <stdio.h> #define show(x,s) printf("%d", x); \ printf(s); int main(){ int x; printf("Enter an integer: "); scanf( "%d", &x); if( x % 2 ) show(x, " is odd\n"); else show(x, " is the magic number!\n"); } Harry Koehnemann, Computing Studies

  10. The do-while solution • we can “swallow” the semi-colon by doing a crazy kluge with a do-while loop because it is a SINGLE statement (that ends in a semi-colon) • write the macro as #define macroName()do{statement1; \ statement2; \ statementn;} \ while(0) Harry Koehnemann, Computing Studies

  11. Variadic Macros • A function-like macro can be declared to accept a variable number of arguments: #define eprintf(...) fprintf (stderr, __VA_ARGS__) • All the tokens in its argument list after the last named argument, including any commas, become the variable argument. This sequence of tokens replaces the identifier __VA_ARGS__ in the macro. Harry Koehnemann, Computing Studies

  12. Variadic Example Macro: #define eprintf(...) fprintf (stderr, __VA_ARGS__) Reference to macro: eprintf ("%s:%d: ", input_file, lineno) Will be expanded to: fprintf (stderr, "%s:%d: ", input_file, lineno) Harry Koehnemann, Computing Studies

  13. Including Files • The #include directive allows you to “insert” source code from other files. • The #include is most often used with header files. • System header files declare the interfaces to parts of the operating system. They are specified with<> around name. • #include <stdio.h> • You can create your own header files that contain macros and declarations for interfaces common to the source files of your program. • #include “myheader.h” • Including a header file produces the same results as copying the header file into each source file that needs it. Harry Koehnemann, Computing Studies

  14. myHeader.h #include <stdio.h> #include "myHeader.h" int main(){ int x; x = guess(); if( x < MAGIC_NUM ) show(x, " is too low\n"); else if( x > MAGIC_NUM ) show(x, " is too high\n"); else show(x, " is the magic number!\n"); } #include "functs.c" #define MAGIC_NUM 13 #define MIN 1 #define MAX 100 #define show(x,s) \ do{ printf("%d", x); \ printf(s);} \ while(0) int guess(); functs.c int guess(){ int x = MIN -1; printf("Guess a positive integer between %d and %d: ", MIN, MAX ); scanf("%d", &x ); while( x < MIN || x > MAX ){ printf("Invalid – guess must between %d and %d: ", MIN, MAX ); scanf("%d", &x ); } return x; } Harry Koehnemann, Computing Studies

  15. Undefining macros • If a macro ceases to be useful, it may be undefined with the #undef directive. • #undef takes a single argument, the name of the macro to undefine. • a new macro (that has same name as old) can be defined later in the code, and its definition will be used after the point of its definition. Harry Koehnemann, Computing Studies

  16. Issues with separate compilation • In the guessGame example, what happens if we try to compile “functs.c” alone (using –c flag)? WHY? • Solution: #include “myHeader.h” in functs.c. What happens when we try to compile functs.c alone? What happens when we compile guessGame.c? Harry Koehnemann, Computing Studies

  17. Motivation for separate compilation #include <stdio.h> #include "myTypes.h" void init( List * myList ){ myList->head = NULL; myList->tail = NULL; myList->length = 0; } void add( List * myList, int val ){ Node * n = (Node*) malloc(sizeof(Node)); n->data = val; n->next = myList->head; myList->head = n; (myList->length)++; } void print( List myList ){ int i; Node * temp = myList.head; for( i = 0; i < myList.length - 1; i++ ){ printf( "%d -> ", temp->data ); temp = temp->next; } printf( "%d", temp->data ); } #include<stdio.h> #include "myTypes.h" int main(){ List L; init( &L ); add( &L, 2 ); add( &L, 7 ); printf(" L = " ); print( L ); printf( "\n" ); } #include "listFuncts.c" Harry Koehnemann, Computing Studies

  18. myTypes.h typedef struct Node_struct{ int data; struct Node_struct * next; } Node; typedef struct List_struct{ Node * head; Node * tail; int length; } List; void add( List * , int ); void print( List ); void init( List * ); Harry Koehnemann, Computing Studies

  19. Bitwise Example #ifndef BITWISE_H_ #define BITWISE_H_ /* A 16-bit integer number is broken up as follows: * #bits position * 1 0 read permission * 1 1 write permission * 4 2-5 user id * 2 6-7 unused - should always be 0 * 8 8-15 character byte */ #define SET_READABLE 0x1 #define SET_WRITEABLE 0x2 #define SET_USERID(id) (id<<2) #define SET_CHAR(c) (c << 8) #define READ_MASK 0x0001 #define WRITE_MASK 0x0002 #define USERID_MASK 0x003C #define CHAR_MASK 0xFF00 #define IS_READABLE(desc) ( (desc & READ_MASK) >> 0) #define IS_WRITEABLE(desc) ( (desc & WRITE_MASK) >> 1) #define USERID(desc) ( (desc & USERID_MASK) >> 2) #define CHAR_VALUE(desc) ( (desc & CHAR_MASK) >> 8) #endif/*BITWISE_H_*/ Harry Koehnemann, Computing Studies

  20. Bitwise Example #include <stdio.h> #include"bitwise.h" void displayValues(int desc); // declare function int main() { displayValues(0x413F); // Who can read this!!! displayValues(SET_READABLE | SET_WRITEABLE | SET_USERID(0xF) | SET_CHAR('A')); displayValues(SET_WRITEABLE | SET_CHAR('B')); return 0; } void displayValues(int desc) { printf("Descriptor is %x (read:%d, write:%d, userid:%d, char:%c)\n", desc, IS_READABLE(desc), IS_WRITEABLE(desc), USERID(desc), CHAR_VALUE(desc)); } Descriptor is 413f (read:1, write:1, userid:15, char:A) Descriptor is 413f (read:1, write:1, userid:15, char:A) Descriptor is 4103 (read:0, write:1, userid:0, char:B) Harry Koehnemann, Computing Studies

  21. Conditional Compiling • This preprocessing feature lets us designate parts of a program which may or may not be compiled. • #ifdef symbol .... {#else} #endif • #ifndef symbol .... {#else} #endif • One common application of conditional compilation is for inclusion/exclusion of debugging statements • Another common application is to “protect” information in header files that might be included in multiple source files. Harry Koehnemann, Computing Studies

  22. Conditional Compiling cont... • Other directives: • #if • #elif • #else • #endif Example: #if SYSTEM == SYSV #define HDR “sysv.h” #elif SYSTEM == BSD #define HDR “bsd.h” #else #define HDR “default.h” #endif #include HDR Harry Koehnemann, Computing Studies

  23. #pragma directives • A #pragma directive is used to provide additional information to the compiler (beyond what is conveyed in the language itself) • A pragma has the following form: • #pragma characterSequence • characterSequence is not subject to macro substitution • E.g., • #pragma GCC system_header tells the compiler to treat the current file as if it came from a system header • #pragma align alignment (variable [, variable]...) tells the compiler to increase the minimum alignment of each variable to alignment Harry Koehnemann, Computing Studies

  24. References • http://www.ece.utexas.edu/~valvano/embed/chap11/chap11.htm • http://www.ugcs.caltech.edu/info/gcc/cpp_3.html#SEC14 • http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html#Pragmas Harry Koehnemann, Computing Studies

More Related