Macros in C/C++
Total Page:16
File Type:pdf, Size:1020Kb
Macros in C/C++ Computer Science and Engineering College of Engineering The Ohio State University Lecture 33 Macro Definition Computer Science and Engineering The Ohio State University Directive: #define #define <name> <body> Example: #define BUFF_SIZE 1000 A newline ends the macro body Macros can only be 1 line long Work-around: For longer bodies, use the line continuation character, \ Naming convention: SCREAMING_SNAKE_CASE Common use: compile-time constant int Buffer[BUFF_SIZE]; Also: #undef GNU gcc Toolchain Computer Science and Engineering The Ohio State University Run only macro preprocessor: -E $ gcc –E test.c > test.i Standard file extension for preprocessed C (C++) is .i (.ii) More than just expanding macros: Begins by stripping comments Concatenates lines marked with \ May collapse white space Adds markers for filename and line numbers to help connect later errors to original location in source file Text Substitution Computer Science and Engineering The Ohio State University Gcc preprocessor doesn't really care that input is a C program… Theoretically can be used on any text file Demo: ulisse.c, ulisse.ii Caveat: The preprocessor does rely on proper C conventions for tokenizing Apostrophes will mess things up In practice: preprocessing something other than C/C++ files with gcc is a hack, it is brittle, and it is probably a bad idea Algorithmic Highlights Computer Science and Engineering The Ohio State University Single pass Forward references are not expanded Nested invocation is permitted Expanded body is rescanned for more invocations Nested definitions are not permitted No recursion or mutual recursion Self references are not further expanded Circularity (mutual recursion) handled similarly: First cyclic reference is not expanded Nesting Forward References Computer Science and Engineering The Ohio State University Input Input foo = X; #define SIZE BUFF #define X 4 #define BUFF 1024 bar = X; Mem[SIZE]; Output Output foo = X; Mem[1024]; bar = 4; Still Single Pass Computer Science and Engineering The Ohio State University Input #define BUFF 1024 #define SIZE BUFF #undef BUFF #define BUFF 2048 Mem[SIZE]; Output? Macro Arguments Computer Science and Engineering The Ohio State University Argument list follows name, without spaces #define <name>(<arglist>) <body> Example #define INC(X) X++ #define SUM(X,Y) X+Y Danger: Arithmetic grouping Macro is doing text substitution, not programming language call Scope issues may cause surprising problems Problem: Unprotected Body Computer Science and Engineering The Ohio State University Recall ternary operator ( _ ? _ : _ ) Consider #define MAX(X,Y) X > Y ? X : Y Do these work? a = MAX(b,c); a = MAX(b,c) + 1; Result of expansion: a = b > c ? b : c; a = b > c ? b : c + 1; Solution: protect the body #define MAX(X,Y) (X > Y ? X : Y) Problem: Unprotected Args Computer Science and Engineering The Ohio State University Consider another use of MAX macro flag = MAX(b<0,c<0); A disjunction of the two conditions? Result of expansion: flag = (b<0 > c<0 ? b<0 : c<0); Solution: protect the arguments #define MAX(X,Y) ((X) > (Y) ?(X):(Y)) flag = ((b<0) > (c<0) ?(b<0):(c<0)); Conditional Expansion Computer Science and Engineering The Ohio State University Common condition “is this macro (not) defined?” #ifndef BUFF_SIZE #define BUFF_SIZE 1024 #endif /*BUFF_SIZE*/ Application: debugging modes #define DEBUG_ON . #ifdef DEBUG_ON printf ( . ); #endif /*DEBUG_ON*/ Advantage: No space/time overhead Disadvantage: Change requires recompiling File Inclusion Computer Science and Engineering The Ohio State University Syntax #include "<filename>" Effect: Contents of <filename> inserted at that point #include “f” Danger: Repeated Inclusion Computer Science and Engineering The Ohio State University Multiple inclusion of the same file can lead to conflicts, eg double declaration File f1 includes lib1 and lib2 File lib1 includes lib2 Result: f1.i contains two copies of lib2 In the extreme: recursive inclusion File f1 includes f2 File f2 includes f1 Solution: Conditional Computer Science and Engineering The Ohio State University Protect every file that will be included by other file(s) Convention Wrap entire file in #ifndef … #endif Inside, define a unique macro (1/file) Example, file cat.h #ifndef CAT_H_PAGS #define CAT_H_PAGS ... #endif /*CAT_H_PAGS*/ Predefined Macros Computer Science and Engineering The Ohio State University Macros provided by the preprocessor Some are part of ANSI language standard __FILE__ : current file name __LINE__ : this line number in current file __DATE__ / __TIME__ : current date/time Some are compiler-specific (eg gcc) __VERSION__ __BASE_FILE__ __INCLUDE_LEVEL__ Example use: Error or debug messages printf("error in %s, line %d\n", __FILE__, __LINE__); Using Arguments in Strings Computer Science and Engineering The Ohio State University ANSI C: Parameter substitution is not performed within quoted strings Example #define DISP(EXP) \ printf("EXP = %d\n", EXP) DISP(i*j+1) Result of expansion: printf("EXP = %d\n", i*j+1) Solution: "Stringizing" operator, # #define DISP(EXP) \ printf(#EXP " = %d\n", EXP) Result of expansion: printf("i*j+1" " = %d\n", i*j+1) Pitfall: Side effects Computer Science and Engineering The Ohio State University Macros look like function calls Text substitution means semantics are not the same as function calls Example: Recall MAX macro #define MAX(X,Y) ((X) > (Y) ?(X):(Y)) a = MAX(b++, c++) If b = 2, and c = 5 beforehand, what is the result? // a = ____, b = ____, c = ____ Pitfall: Swallow the Semicolon Computer Science and Engineering The Ohio State University Macro consists of compound statement #define INC(X,Y) {X++; Y++} Tempting to use macro with semicolon INC(a, b); However, consider: if (…) INC(a, b); else … Result: compile-time error Solution: (notice missing semicolon) #define INC(X, Y) \ do { X++; Y++ } while(0) Summary Computer Science and Engineering The Ohio State University Macro definition with #define Single pass No forward references No nested definitions Nested invocations expanded (no cycles) Arguments are permitted Conditional expansion #ifdef File inclusion #include Coding idioms to prevent some mistakes Protect the body, protect the arguments Avoid arguments with side effects.