INF: Preprocessor Condenses Multiline Macro Invocations

ID Number: Q50341

5.00 5.10 6.00 6.00a 6.00ax | 5.10 6.00 6.00a

MS-DOS | OS/2

Summary:

The preprocessor of the Microsoft C Optimizing Compiler versions 5.0,

5.1, 6.0, 6.0a, and 6.0ax does not preserve the source code structure

of macro invocations upon expansion. Preprocessor macro expansion is

carried out on one line at a time, in a left to right fashion, until

the end-of-line is reached. Thus, when multiple-line macro invocations

are expanded, they are converted into a single line of code.

The following example defines a simple macro and displays this

conversion of multiline macro invocations:

#define macro( arg1, arg2, arg3 ) arg1 + arg2 + arg3

Source Code Preprocessor Listing

----------- --------------------

value = macro ( param1, value = macro( param1 + param2 + param3 );

param2,

param3 );

Note that the preprocessor listing replaces the three lines of code

in the source file with only one line. As a result, the line numbers

between the two files are different because the preprocessor does not

perform any line number adjustment.

This may cause problems if you must compile preprocessor listings to

avoid errors generated by .C source files (for example, insufficient

heap space). When the preprocessor listing is compiled, the subtle

side effect becomes more obvious in the form of discrepancies between

original source-code line numbers and line numbers associated with

compiler errors or debugger maps. This result can make debugging

original source code difficult, and can be a general nuisance when

trying to locate erroneous lines in source code indicated by the

compiler.

The #line directive and the __LINE__ predefined macro can be used to

redefine preprocessor listing line numbers and eliminate such

differences. To compensate for the preprocessor single-line expansion

of macro invocations, place the directive "#line __LINE__" in the

source code line following the macro invocation.

The #line directive, which accepts an integer constant as an argument,

instructs the preprocessor to change the compiler's internally stored

line number to the integer argument specified. The __LINE__ macro,

which is supplied as the argument to the #line directive, evaluates to

the current line number generated during preprocessing. Working

together, they force the compiler to generate consistent line numbers

between the the source file and the preprocessor listing.

The program below illustrates the macro expansion behavior of the C

preprocessor and how it can be modified to generate

line-number-compatible source and preprocessor listings.

More Information:

/* TEST.C */ | /* TEST.I */

|

/*1*/ #define sum( a,b,c) a+b+c | /*1*/ #define sum(a,b,c) a+b+c

/*2*/ | /*2*/

/*3*/ void main( void ) | /*3*/ void main( void )

/*4*/ { | /*4*/ {

/*5*/ int i; | /*5*/ int i;

/*6*/ i = sum( 1, | /*6*/ i = sum( 1, 2, 3 );

/*7*/ 2, | /*7*/ /* #line __LINE__ */

/*8*/ 3 ); | /*8*/ i = 100000;

/*9*/ /* #line __LINE__ */ | /*9*/ }

/*10*/ i = 100000; | /*10*/

/*11*/ } | /*11*/

|

When the program TEST.C above is compiled under warning level 3, a

data conversion warning is generated for line 10, indicating overflow

of the integer variable i. TEST.C is then run through the preprocessor

using the /P compiler option, where TEST.I (above) is generated.

Compiling TEST.I under warning level 3 generates the same data

conversion warning, but on line 8. The line number difference between

TEST.C and TEST.I is obvious.

By uncommenting line 9 in TEST.C, both the source file and

preprocessor listing contain consistent line numbers following the

macro invocation, because the line number is reset to the proper value

(7) after the preprocessor pass.

Additional reference words: 5.00 5.10 6.00 6.00a 6.00ax