Preprocessor

Objectives

• Describe preprocessor commands

– syntax – common use

2

Preprocessing

• C# offers preprocessing – first stage of translation – performed by the compiler – evaluates preprocessor directives • The term preprocessor is historical – comes from the C/C++ tradition – preprocessor was separate program that ran before compiler

3

Preprocessor directives

• Available preprocessor directives

– #define – #undef – #if – #else – #elif – #endif – #line – #warning – #error – #region – #endregion

4

Basic syntax

• Preprocessing directive must be only statement on a line

– leading whitespace ok

leading whitespace

static void Main() {

#if Logging

...

}

5

Creating symbols

• Can create conditional compilation symbol – syntax: #define followed by symbol – must go at beginning of file – applies only to that file – ok to define same symbol more than once

create symbol

#define Logging

...

6

Compiler option

• Can use compiler option to create symbol – syntax: /define: followed by symbol – applies to all files in compilation command

use compiler option

C:\> csc /define:Logging MyApplication.cs

7

Symbol states

• Symbols have only two states

– defined – undefined

• States correspond to Boolean values

– defined = true – undefined = false

symbol now defined, has value true

#define Logging

...

8

Removing symbols

• Can remove symbol definition

– syntax: #undef followed by symbol – must go at beginning of file – applies only to that file – ok if symbol is not defined – useful to turn off symbol created with compiler option

remove symbol

#undef Logging

...

9

Testing symbol

• Several options for testing symbol status

– #if ... #endif – #if ... #else ... #endif – #if ... #elif ... #endif

• Boolean value of symbol used in test

– true = guarded code passed to next stage of compilation – false = guarded code eliminated

static void Main() {

#if Logging

code included only if symbol defined

Console.WriteLine("enter main");

#endif

}

10

Preprocessing expression

• Symbol test can be logical expression

– available operators: ! == != && || – parentheses can be used to group sub-expressions

test for not defined

#if !Logging

both must be true

...

#if Logging && Debugging

...

both must have same value, either true or false

#if Logging == Debugging

...

11

Controlling line number and file name

• Control line and file reported by compiler with #line

– #line number - change line – #line number "filename" - change line and filename – #line default - restore true line numbers and filenames

class Test {

report line numbers counting from 1

override line and file

restore accurate reporting

static void Main() {

#line 1 ... #line 5 "Source.cs" ... #line default ...

}

}

12

Diagnostic directives

• Can generate compile time warnings and errors

– #warning – #error

warning

#if FinalReview

#warning Recent change: updated 07-Nov-03 by MAT

#endif

error

#if Logging && MaximizePerformance

#error Turn off logging to maximize performance

#endif

13

Regions

• Create logical group with #region and #endregion

– have no effect on meaning of code – can supply name for region – can be convenient for programmer – can be read by development tools

class Stock {

fields

#region Private fields private string name; private double price; private int shares;

#endregion

constructors

#region Constructors

public Stock(string name, double price, int shares) { ... }

#endregion

...

}

14

Summary

• C# compiler offers preprocessing as first stage of translation

– can conditionally compile code – can control line numbers and file names reported by compiler – can emit warnings and errors – can define logical regions of source code

15