58
CMPE-013/L: “C” Programmin riel Hugh Elkaim – Spring 2013 CMPE-013/L Pre-Processor Commands Gabriel Hugh Elkaim Spring 2013

CMPE-013/L Pre-Processor Commands

  • Upload
    elisa

  • View
    37

  • Download
    0

Embed Size (px)

DESCRIPTION

CMPE-013/L Pre-Processor Commands. Gabriel Hugh Elkaim Spring 2013. Introduction. Preprocessing Affect program preprocessing and execution Capabilities Inclusion of additional C source files Definition of symbolic constants and macros Conditional preprocessing of a program - PowerPoint PPT Presentation

Citation preview

Page 1: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

CMPE-013/L

Pre-Processor Commands

Gabriel Hugh ElkaimSpring 2013

Page 2: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Introduction

• Preprocessing

– Affect program preprocessing and execution– Capabilities

• Inclusion of additional C source files• Definition of symbolic constants and macros• Conditional preprocessing of a program

• Format of preprocessing directivesA preprocessing directive consists of a sequence of preprocessing tokens thatbegins with a pound sign #, which must be the first non-space character on the line. Some preprocessing directives are listed below.

Page 3: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

PreProcessor Directives

• Conditional Compilation• Symbolic Constants and Macros• Source File Inclusion• Macros• Predefined Macros• Line Control• Error Directive

Definition

PreProcessor Directives are parts of the code that give special instructions to the compiler. They always begin with a # at the beginning of the line, and are used to direct the compiler with a number of specific commands.

Page 4: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Directive Description #define Define a preprocessor macro. #elif Alternatively include some text based on the value of another

expression, if the previous #if, #ifdef, #ifndef, or #elif test failed. #else Alternatively include some text, if the previous #if, #ifdef, #ifndef, or

#elif test failed. #endif Terminate conditional text.

#error Produce a compile-time error with a designated message.

#if Conditionally include text, based on the value of an expression.

#ifdef Conditionally include text, based on whether a macro name is defined.

#ifndef Conditionally include text, based on if a name is not a defined macro.

#include Insert text from another source file.

#line Give a line number for message.

#pragma Compiler/interpreter specific features, not in C standard

# Null directive

defined Preprocessing operator that yields 1 if a name is defined as a preprocessing macro and 0 otherwies; used in #if and #elif.

Page 5: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Symbolic Constants and Macros

• The #define Preprocessing Directive

– This preprocessing directive is used to create symbolic constants and macros.

• Form

#define identifier replacement-list

defines an object-like macro that causes each subsequent instance of the macro names to be replaced by the replacement-list of preprocessing tokens that constitute the remainder of the directive. The new-line is a character that terminates the #define preprocessing directive.

Page 6: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

• Symbolic constantsThe simple form of macro is particularly useful for introducing namedconstants into a program. It allows for easier modification of theconstants later on.When programs are processed, all occurrences ofsymbolic constants indicated by identifier are replaced by thereplacement-list.

Example: #define BLOCK_SIZE 0x100

we can write int size = BLOCK_SIZE; instead of int size = 0x100; in the program. Note: Cannot redefine symbolic constants with different values by multiple #define statements

Symbolic Constants and Macros

Page 7: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

• A preprocessing directive of the form

#define identifier(identifier-list-opt) replacement-list new-line

defines a function-like macro with arguments, similar syntactically to a function call. The parameters are specified by the optional list of identifiers.

Example: if a macro mul with two arguments is defined by

#define mul(x,y) ((x)*(y))

then the source program line

result = mul(5, a+b);

is replaced with

result = ((5)*(a+b));

Symbolic Constants and Macros

Page 8: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

NOTE: Parentheses are important in macro definitions.

Example: If macro mul is defined as

#define mul(x,y) (x*y)

The statement result = mul(5, a+b); in the source program becomes result = (5*a+b); The evaluation will be incorrect.

Page 9: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

• #undef– Undefine a symbolic constant or macro, which can later be

redefined.

Example:

#define mul(x,y) ((x)*(y)) /* … */ #undef mul int mul; /* mul can be used after it is undefined */

Page 10: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Source File Inclusion• The #include Preprocessing Directive

– Copy of a specified header file included in place of the directive. It has following two common forms. 1)#include <header.h>

– Searches standard library for header file and replaces the directive by the entire contents of the file.

– In Ch, the header is searched according to the paths specified by the the system variable _ipath. C compilers in Unix will typically search the header file in the directory /usr/include. In Visual C++, the header file is searched based on the paths in the environment variable INCLUDE.

or cl –I C:/home/assount/include program.c

– Used for standard library files2) #include “header.h"

– C compilers and interpreters will first search the header file in the same directory where the file is being processed, which typically is the current directory.

– Then search the header file in the paths as if it was included by #include <header.h>.

Page 11: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

• Applications

– Loading header files #include <stdio.h>– Programs with multiple source files to be

compiled together– Includes user defined header files which have

common declarations and definitions (classes, structures, function prototypes, and macros)

Page 12: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Conditional Compilation

• Conditional compilation – Enables the user to control the compilation of the program,

screen out portions of source code that are not to be compiled.

• Structure– The structure is similar to if and else statement in C.

• Conditional preprocessing directives– #if, #else, #elif, and #endif

Page 13: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

• Preprocessing directives of the forms

#if expr1 /* ... */ #elif expr2 /* ... */ #else /* ... */ #endif

check whether the controlling expression evaluates to nonzero. Every #if ends with #endif

Example:

#if defined(_HPUX_) printf(“I am using HP-UX\n”); #elif defined(_WIN32_) printf(“I am using Windows\n); #endif

Page 14: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

• Preprocessing directives of the forms

# ifdef identifier# ifndef identifier

check whether the identifier is or is not currently defined as a macro name.

– #ifdef identifier is the short form of

#if defined(identifier)

– #ifndef identifier is the short form of

#if !defined(identifier)

• Each directive’s condition is checked in order. If it evaluates to false (zero), then the group that it controls is skipped: directives are processed only through the name that determines the directive in order to keep track of the level of nested conditionals.

• Only the first group whose control condition evaluates to true (nonzero) is processed. If none of the conditions evaluates to true, and there is a #else directive, then the group controlled by the #else is processed; if lacking a #else directive, then all the groups until the #endif are skipped.

Page 15: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

• Comment out a segment of code– Comment out code segment which contains /* ... */– Use following format to comment out the segment of code

double d = some_func(); #ifdef JUNK

/* This code segment will be commented out */printf(“d = %f\n”, d);

#endif

The code segment will be commented out when JUNK is not defined, To uncomment the code segment, define JUNK or remove #ifdef JUNK and #endif.

Page 16: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

• To include a header file in a program only once, it istypically handled using the combination of the followingpreprocessing directives #ifndef, #define, and #endif. For example, a header file header.hmay consist of the following code fragment.

#ifndef HEADER_H #define HEADER_H /* code */ #endif

Page 17: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

/* File: accel.h */#ifndef ACCEL_H#define ACCEL_H

#define M_G 9.81

double force(double t);double accel(double t, double mu, double m);

#endif

/* File: accelhead.c */#include <stdio.h>/* local header file */#include "accel.h"

int main() { /* declare variables */ double a, mu, m, t;

/* Initialize variables */ mu = 0.2; m = 5.0; t = 2.0; /* processing */ a = accel(t, mu, m); /* display the output and termination */ printf("Acceleration a = %f (m/s^2)\n", a); return 0;}

double force(double t) { double p;

p = 4*(sin(t)-3)+20; return p;}

double accel(double t, double mu, double m) { double a, p;

p = force(t); a = (p-mu*m*M_G)/m; return a;}

Example:

Page 18: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Predefined Macros• Macros defined in C

Macro Name Description

__LINE__ The line number of the current source program line which is expressed as a decimal integral constant

__FILE__ The name of the current source file which is expressed as a string constant.

__DATE__ The calendar date of the translation which is expressed as a string constant form “Mmm dd yyy”. Mmm is produced by asctime().

__TIME__ The current time which is expressed as a string constant of the form “hh:mm:ss”, as returned by asctime().

__STDC__ The decimal constant 1 for C comforming impelementtation.

__STDC_VERSION__ The decimal constant 199901L for C99 comforming implementation

Page 19: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Example:/* filename: predefined.c */#include <stdio.h>

int main() { printf("__FILE__ = %s\n", __FILE__); printf("__LINE__ = %d\n", __LINE__); printf("__DATE__ = %s\n", __DATE__); printf("__TIME__ = %s\n", __TIME__);#ifdef __STDC__ printf("__STDC__ = %d\n", __STDC__);#endif#ifdef __STDC_VERSION___ printf("__STDC_VERSION__ = %d\n", __STDC_VERSION__);#endif return 0;}

Page 20: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Output:

__FILE__ = predefined.c __LINE__ = 6 __DATE__ = Feb 24 2003 __TIME__ = 00:09:42 __STDC__ = 1 __STDC_VERSION_ = 199901

Page 21: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

/* File: printerror.c */#include <stdio.h>#define printerror() printf("Error in %s:%s():%d\n", \ __FILE__, __func__, __LINE__);

void funcname1() { printerror();}void funcname2() { printerror();}

int main() { funcname1(); funcname2(); return 0;}

Example

Error in printerror.c:funcname1():7Error in printerror.c:funcname2():10

Output

Page 22: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

NULL Directive

• A preprocessing directive of the form #new-line

has no effect on the program.

• The line is ignored.

Page 23: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

• Debugging code

#define DEBUG

/* ... */ double x; x = some_func();

#ifdef DEBUG printf(“The value of x = %f\n”, x); #endif

– Defining DEBUG to print out the value of x.– After debugging, remove #define statement. The debugging

statements are ignored.

Page 24: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Line Control

• The #line directive can be used to alter the line numbers assigned to the source code. This directive gives a new line number to the following line, which is then incremented to derive the line number for subsequent lines.

• A preprocessing directive of the form

#line digit-sequence new-line

causes the implementation to behave as if the following sequence of source lines begins with a source line that has a line number as specified by the digit sequence.

• A preprocessing directive of the form

#line digit-sequence “s-char-sequence-opt” new-line

sets the presumed line number similarly and changes the presumed name of the source file to be the contents of the character string literal. The name of the source file is stored in the predefined macro __FILE__ internally.

Page 25: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Example:

/* FILENAME: linefile.c */ #include <stdio.h>

int main() { printf(“before line directive, line number is %d \n”, __LINE__); printf(“the FILE predefined macro = %s\n”, __FILE__); #line 200 “newname” printf(“after line directive, line number is %d \n”, __LINE__); printf(“The FILE predefined macro = %s\n”, __FILE__); return 0;}

Output:

before line directive, line number is 4 the FILE predefined macro = linefile.c after line directive, line number is 200 the FILE predefined macro = newname

Page 26: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

PreProcessor Directives

• Macros:– #define text(args) …– Can be used instead of functions in certain instances– Made to look like C functions

Definition

Macros are text replacements created with #define that insert code into your program. Macros may take parameters like a function, but the macro code and parameters are always inserted into code by text substitution.

Page 27: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Macros with #define

• Macros– Are evaluated by the preprocessor– Are not executable code themselves– Can control the generation of code before the

compilation process– Provide shortcuts

Definition

Macros are text replacements created with #define that insert code into your program. Macros may take parameters like a function, but the macro code and parameters are always inserted into code by text substitution.

Page 28: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Macros with #defineSimple Macros

• Text substitution as seen earlierSyntax

#define label text

Every instance of label in the current file will be replaced by texttext can be anything you can type into your editorArithmetic expressions evaluated at compile time

Example

#define Fosc 4000000#define Tcy (0.25 * (1/Fosc))#define Setup InitSystem(Fosc, 250, 0x5A)

Page 29: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Macros with #defineArgument Macros

• Create a function-like macroSyntax

#define label(arg1,…,argn) code

The code must fit on a single line or use '\' to split linesText substitution used to insert arguments into codeEach instance of label() will be expanded into codeThis is not the same as a C function!

Example

#define min(x, y) ((x)<(y)?(x):(y))#define square(x) ((x)*(x))#define swap(x, y) { x ^= y; y ^= x; x ^= y; }

Page 30: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Macros with #defineArgument Macros – Side Effects

Example

#define square(a) ((a)*(a))Extreme care must be exercised when using macros.Consider the following use of the above macro:i = 5;x = square(i++);

x = 30i = 7

Results:x = square(i++);expands to:

x = ((i++)*(i++));So i gets incremented twice, not once at the end as expected.

Wrong Answers!

Page 31: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

• The # token appearing within a macro definition is recognized as a unary stringization operator.

• In a replacement list, if a parameter is immediately preceded by a # preprocessing token, both are replaced by a single character string literal preprocessing token that contains the spelling of the preprocessing token sequence for the corresponding argument.

Example:

> #define TEST(a) #a> printf(“%s”, TEST(abcd))abcd

– The macro parameter abcd has been converted to the string constant “abcd”. It is equivalent to

> printf(“%s”, “abcd”)

Converting Token to Strings

Page 32: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

• Each occurrence of white space between the argument’s preprocessing tokens becomes a single space character in the character string literal. White space before the first preprocessing token and after the last preprocessing token composing the argument is deleted.

Example:

> #define TEST(a) #a> printf(“1%s2”, TEST( a b ))1a b2

– The argument is turned into the string constant “a b”.

Page 33: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Token Merging in Macro Expansions• The merging of tokens to form new tokens in C is controlled by the

presence of the merging operator ## in macro definitions.• The common use of concatenation is concatenating two names into a

longer name. It is possible to concatenate two numbers, or a number and a name, such as ‘1.5’ and ‘e3’, into a number.

Example:

> #define CONC2(a, b) a ## b> #define CONC3(a, b, c) a ## b ## c> CONC2(1, 2)12 // numbers ‘1’ and ‘2’ concatenated to ‘12’> CONC3(3, +, 4)7 // ‘3’, ‘+’, and ‘4’ becomes ‘3+4’, which equals

‘7’ > printf(“CONC2(1,2) = %d”, CONC2(1,2)) CONC2(1,2) = 12

Page 34: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

• A preprocessing directive of the form #error pp-tokens-opt new-line

causes the implementation to produce a diagnostic message that includes the specified sequence of preprocessing tokens and the interpretation to cease.

Example:

/* FILENAME: error.c */ #include <stdio.h> #define MACRO int main() { #ifdef MACRO #error This is an error, if your code reach here /* the code here will not be processed */ #else printf("ok \n"); #endif return 0; }

Error Directive

Page 35: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Output:

ERROR: #error: This is an error, if your code reach hereERROR: syntax error before or at line 6 in file ’error.c' ==>: #error This is an error, if your code reach here BUG: #error This is an error, if your code reach here<== ???WARNING: cannot execute command ‘error.c’

Page 36: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Lab Exercise 19

Macros with #define

Page 37: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Exercise 19#define Macros

• Open the project’s workspace:

1 Open MPLAB® and select Open Workspace… from the File menu.Open the file listed above.If you already have a project open in MPLAB, close it by selecting Close Workspace from the File menu before opening a new one.

/Examples/Lab19.zip -> Load “Lab19.mcw”On the class website

Page 38: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Exercise 19#define Macros

• Compile and run the code:

2 Click on the Build All button.

Compile (Build All) Run2 3

3 If no errors are reported,click on the Run button.

Halt4

4 Click on the Halt button.

Page 39: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Exercise 19#define Macros

/*---------------------------------------------------------------------------- MACROS----------------------------------------------------------------------------*/#define square(m) ((m) * (m))#define BaudRate(DesiredBR, FoscMHz) ((((FoscMHz * 1000000)/DesiredBR)/64)-1)

/*============================================================================ FUNCTION: main()============================================================================*/int main(void){

x = square(3);printf("x = %d\n", x);

SPBRG = BaudRate(9600, 16);printf("SPBRG = %d\n", SPBRG);

}

#define Macro Definition and Use

Page 40: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Exercise 19Conclusions

• #define macros can dramatically simplify your code and make it easier to maintain

• Extreme care must be taking when crafting a macro due to the way they are substituted within the text of your code

Page 41: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Questions?

Page 42: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 43: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 44: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 45: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 46: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 47: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 48: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 49: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 50: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 51: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 52: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 53: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 54: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 55: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 56: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 57: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013

Page 58: CMPE-013/L Pre-Processor Commands

CMPE-013/L: “C” ProgrammingGabriel Hugh Elkaim – Spring 2013