CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads...

28
Outline What is it? Directives Macros More more or less interesting characteristics End CPP The C Preprocessor Nils Mosch ¨ uring PhD Student (LMU) Nils Mosch ¨ uring PhD Student (LMU) , CPP 1

Transcript of CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads...

Page 1: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

CPPThe C Preprocessor

Nils MoschuringPhD Student (LMU)

Nils Moschuring PhD Student (LMU) , CPP 1

Page 2: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

1 What is it?

2 DirectivesConstant MacrosConstant MacrosFile InclusionConditional CompilationFurther Directives

3 MacrosSimple MacrosMultiline macrosMacro FunctionsMore Problems

4 More more or less interesting characteristicsMacros containing macrosMacros containing macro definitionsVariadic Macros

5 End“Interesting tasks”Overview

Nils Moschuring PhD Student (LMU) , CPP 2

Page 3: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

What is it?

The C preprocessor is an important tool when programming in C.

It reads a source file, modifies it, following some rules and supplies theresult to the compiler.

Any line which contains a # as the first non-white space character isprocessed by the preprocessor.

There can be white-spaces after the # as well.

Following this # certain C preprocessor directives may be included.

Most compilers can be stopped after preprocessing. Using gcc this isdone via gcc -E.

Nils Moschuring PhD Student (LMU) , CPP 4

Page 4: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Constant Macros

Constant macros can be defined using the following directive:

#define name text

name must be an identifier (following C standard). All subsequent encountersof name will replaced with text.This macro expansion or substitution can be stopped using

#undef name

These are commonly used for symbolic constants:

#define PI 3.14#define MAX_LENGTH 1024

This avoids having certain magic numbers or constant values in the code.Thus, if these numbers need to change, this change must only be incorporatedat one place in the code.

Nils Moschuring PhD Student (LMU) , CPP 6

Page 5: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Predefined Constant Macros

There are a couple of predefined constant macros which can come in reallyhandy:

__LINE__ integer value, current source code line number__FILE__ constant string, current source file

__FUNCTION__ constant string, current function name__DATE__ constant string “Mmm dd yyyy”, compilation start date__TIME__ constant string “hh:mm:ss”, compilation start time

Handy:

#define HERE printf("HERE: in %s() at %s:%d\n", \__FUNCTION__, __FILE__, __LINE__);

Nils Moschuring PhD Student (LMU) , CPP 7

Page 6: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

File Inclusion

This is what you all already used a couple of times:

#include <stdlib.h>

Using this special directive, the C preprocessor will copy the content of thewhole stdlib.h file into your source code.Try: output of g++ -E test.c containing only that line.

Nils Moschuring PhD Student (LMU) , CPP 8

Page 7: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Conditional Compilation

These directives help

controlling which parts of a program are send to the compiler (and whichare ignored)

building for different platforms

enable or disable debug code

#if, # ifdef, # ifndef constant-expression#else, # elif constant-expression#endif

constant-expression

must evaluate to a constant arithmetic expression and may include macroexpansion.

may include any C operators (==, +, -, ...)

is nonzero the following lines are included until #else, #elif or #endifis encountered.

is a macro name, inclusion happens if the macro is defined.Nils Moschuring PhD Student (LMU) , CPP 9

Page 8: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Conditional Compilation: examples

Since comments can not be nested in can be difficult to comment a block ofcode which includes comments.This helps:

#if 0//Unwanted code#endif

Debugging output can be nicely in-/ and excluded:

#define DEBUG

#ifdef DEBUGprintf("This is debug information\n");#endif

also possible

#if defined DEBUGprintf("This is debug information\n");#endif

Nils Moschuring PhD Student (LMU) , CPP 10

Page 9: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Conditional Compilation: examples

Includeguards facilitate source code management

my header.h

#ifndef MY_HEADER_FILE#define MY_HEADER_FILE

//code

#endif

Now even multiple

my source.c

#include "my_header.h"

won’t hurt.

Nils Moschuring PhD Student (LMU) , CPP 11

Page 10: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

#error directive

Syntax

#error message

When the preprocessor encounters this directive compilation stops andmessage is displayed.

Nils Moschuring PhD Student (LMU) , CPP 12

Page 11: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

#line directive

Syntax

#line linenumber "filename"

This directive changes the values of LINE and FILE to the given values.“filename” is an optional argument.

Nils Moschuring PhD Student (LMU) , CPP 13

Page 12: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Simple Macros

The #define directive can be used in more elaborate ways when employingan argument list.

#define name(arg1, arg2, ..., argn) text

There can be no white-space between the name and the argument list.

This macro will be substituted for any occurrence of its name followed bybraces and an appropriate number of arguments.

The supplied arguments will then be substituted for every occurrence intext.

Example:

#define inc(x) x++inc(my_val);

will be replaced by

my_val++;

Easy enough!Nils Moschuring PhD Student (LMU) , CPP 15

Page 13: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Simple Macros: Problems

Problematic macro definition:

#define MULTI(x, y) x * y

and use case:

int x = MULTI(1 + 2, 3 + 4);

will be

int x = 1 + 2 * 3 + 4;

after preprocessing!Better version:

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

Nils Moschuring PhD Student (LMU) , CPP 16

Page 14: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Simple Macros: Problems

Another problematic definition:

#define ADD_FIVE(a) (a) + 5

and use case:

int x = ADD_FIVE(3) * 3;

will be

int x = (3) + 5 * 3;

after preprocessing!Better version:

#define ADD_FIVE(a) ((a) + 5)

Always put everything in parentheses

Nils Moschuring PhD Student (LMU) , CPP 17

Page 15: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Simple Macros: Multiline macros

In order to enable larger macros expressions involving more sophisticatedfunctions one needs to add a \ to the end of the line.

#define LARGE_MULTI(a,b) ( \(a) \

* \(b) \)

There can not be any white-space after the \!

Nils Moschuring PhD Student (LMU) , CPP 18

Page 16: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Macro Functions: Pasting

In order to combine two tokens in a macro evaluation one can use ##.Example:

#define make_func(x) void x##_func() { \printf("Nothing to do\n"); \}

make_func(nils)make_func(student)

will give

void nils_func() { printf("Nothing to do\n"); }void student_func() { printf("Nothing to do\n"); }

Nils Moschuring PhD Student (LMU) , CPP 19

Page 17: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Macro Functions: String-izing

When invoking the # operator on an argument token inside of a macro, thepreprocessor will string-ize it by enclosing it with quotation marks.Example:

#define string_it(B) #Bstring_it(nils)

will give

"nils"

Nils Moschuring PhD Student (LMU) , CPP 20

Page 18: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Macro Functions: String-izing

More helpful

#define make_func(x) \void x##_func() { \printf("Nothing in" #x "\n"); \}

make_func(nils)

gives

void nils_func() { printf("Nothing in" "nils" "\n"); }

(Consecutive constant strings are always concatenated in C)Even more helpful

#define print_int(x) \printf(#x "has value %d\n", (x)); \

can be used like print int(a+b);

Nils Moschuring PhD Student (LMU) , CPP 21

Page 19: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

More problems

Lets look at this nice macro using XOR operations:(example taken from www.cprogramming.com by author Alex Allain).

#define SWAP(a, b) a ˆ= b; b ˆ= a; a ˆ= b;

This produces the desired result:

SWAP(x, y);

(we wish to employ an extra semicolon since this macro looks like a functioncall)But what about this:

if(x < 0)SWAP(x, y);

This breaks (two XOR’s will always execute).

Nils Moschuring PhD Student (LMU) , CPP 22

Page 20: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

More problems: Solution 1

Solution, compound statement:

#define SWAP(a, b) {a ˆ= b; b ˆ= a; a ˆ= b;}

but:

if(x < 0)SWAP(x, y);

elseSWAP(x, z);

won’t work! The semicolon after the closing braces of the macro ends theconditional directive!

Nils Moschuring PhD Student (LMU) , CPP 23

Page 21: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

More problems: Solution 2

Solution, while loop:

#define SWAP(a,b) do { a ˆ= b; b ˆ= a; a ˆ= b; } while(0)

This will swallow the semicolon. This is actually the best and most accurateway to do this...The loop executes only once and most compilers will not generate extra codefor it.MISSING: Sideeffects in Macro use, i.e.: MAX(x++,y++);

Nils Moschuring PhD Student (LMU) , CPP 24

Page 22: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Macros containing macros

You can write macros which contain other macros. The order does not matter,as there is a rescanning process being performed inside the preprocessorexecution.

#define testB testC#define testA testBtestA

results in

testC

Obvious next step:

#define testB testA#define testA testBtestA

sadly (or luckily) results in results in

testA

Nils Moschuring PhD Student (LMU) , CPP 26

Page 23: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Macros containing macros: recursion

So why does this not do an infinite loop?

If the name of the macro being replaced is found during this scan ofthe replacement list (not including the rest of the source file’spreprocessing tokens), it is not replaced. Furthermore, if any nestedreplacements encounter the name of the macro being replaced, it isnot replaced. These nonreplaced macro name preprocessing tokensare no longer available for further replacement even if they are later(re)examined in contexts in which that macro name preprocessingtoken would otherwise have beenreplaced. (C++ standard, section 16.3.4 paragraph 2)

This essentially means that every macro can only ever be replaced once ineach line of your source code. This is debatable as the C standard containsinconsistencies in this regard.

Nils Moschuring PhD Student (LMU) , CPP 27

Page 24: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Macros containing macros: recursion

#define CAT(a, b) a ## b

#define M_0 CAT(x, y)#define M(a) CAT(M_, a)M(0); // expands to CAT(x, y)

#define N_0() CAT(x, y)#define N(a) CAT(N_, a)()N(0); // expands to xy

(taken from stackoverflow.com, user imre)

Nils Moschuring PhD Student (LMU) , CPP 28

Page 25: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Macros containing macro definitions

This is not possible.

#define include_me #include "my_header.h"include_me

will not include my header.h.There is no rescan process for macro definitions, only for emerging macrosubstitutions.

Nils Moschuring PhD Student (LMU) , CPP 29

Page 26: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Variadic Macros

Macros can be declared using a variable amount of arguments using a similarsyntax used for functions:

#define eprintf(...) fprintf (stderr, __VA_ARGS__)

Nils Moschuring PhD Student (LMU) , CPP 30

Page 27: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Some Problems

Write a preprocessor macro which adds comments to the code.

Write a macro which gives back the number of arguments it as called with.

Solution to the second problem (up to 16 arguments):

#define _NUM_ARGS2(X,X16,X15,X14,X13,X12,X11,X10,X9, \X8,X7,X6,X5,X4,X3,X2,X1,N,...) N

#define NUM_ARGS(...) _NUM_ARGS2(0, __VA_ARGS__ ,16, \15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)

Nils Moschuring PhD Student (LMU) , CPP 32

Page 28: CPP - The C Preprocessor · The C preprocessor is an important tool when programming in C. It reads a source file, modifies it, following some rules and supplies the result to the

Outline What is it? Directives Macros More more or less interesting characteristics End

Overview

We learned about the following Preprocessor directives

#include include a source file#define define a macro#undef undefine a macro#if conditional compilation#ifdef conditional compilation#ifndef conditional compilation#elif conditional compilation#else conditional compilation#endif conditional compilation#line control error reporting#error force an error message#pragma used for implementation-dependent control# null directive; no effect

Nils Moschuring PhD Student (LMU) , CPP 33