MACROS

What is a macro?

Let us start with a somewhat simple-minded example of a macro (not to be emulated in any real project):

#define SquareOf(x) x*x

It defines a kind of function which, used in an actual piece of code, looks exactly like any other function call:

double yout,xin=3;
yout = SquareOf(xin);

As we shall see in a moment, the problem is that SquareOf only pretends to be a function call, while it is really something completely different.

The formal syntax of a macro is:

#define name(dummy1[,dummy2][,…]) tokenstring

The symbols dummy1, dummy2, … are called dummy arguments (as usual, square brackets indicate optional items). There are a few additional rules such as that the macro can extend over several lines, provided one uses a backslash to indicate line continuation:

#define ThirdPowerOf(dummy_argument) \
dummy_argument \
*dummy_argument \
*dummy_argument

How does a compiler handle a macro?

What makes a macro different from a standard function is primarily the fact that a macro is a scripted directive for the compiler (rather than a scripted piece of run-time code) and therefore it gets handled and done with at compilation time rather than at run time.

When the compiler encounters a previously defined macro, it first isolates its actual arguments, handling them as plain text strings separated by commas. It then parses the tokenstring, isolates all occurrences of each dummy-argument symbol and replaces it by the actual argument string. The whole process consists entirely of mechanical string substitutions with almost no semantic testing!

The compiler then substitutes the modified tokenstring for the original macro call and compiles the resulting code script. It is only in that phase that compilation errors can occur. When they do, the result is often either amusing or frustrating, depending upon how you feel at the moment. You are getting mysteriously looking error messages resulting from the modified text and thus referring to something you have never written!

Example 1:

#define SquareOf(x) x*x

void main() {


int Test = 3;

cout << Test << endl;

cout << SquareOf(Test) << endl;

cout << SquareOf(Test + 4) << endl;

cout << SquareOf(Test + Test) << endl;

}

Intuitively, you probably expect the output of this program to be:

3

9

49

36

What you actually get, however, is this:

3

9

19

15

Before you conclude that computers are stupid and become a farmer, consider what has happened. When the compiler met the string “SquareOf(x+4)”, it replaced it with the string “x*x” and then replaced each of the dummy-argument-strings “x” by the actual-argument-string “x+4”, obtaining the final string “x + 4*x + 4” which, in fact, evaluates to 18 and not to the expected 49. Likewise, it is now easy to work out the case of SquareOf(x + x) and understand why and how the result differs from the expected one.

The problem would have never happened if SquareOf(x) were a normal function. In that case, in fact, the argument xin+4 would be first evaluated as a self-standing expression and only then would the result be passed to the function SquareOf for the evaluation of the square.

Actually, none of the two ways is wrong. They are just two different recipes on how to handle the respective scripts. Given the formal similarity between the macro function call to a standard function call, however, the discrepancy is dangerous and should be removed. Fortunately, there is a simple way to do so. Replacing the original definition of the SquareOf macro by

#define SquareOf(x) (x)*(x)

the problem vanishes because, for example, the macro-call string “SquareOf(x+4)” is transformed into “(x)*(x)” and then into “(x+4)*(x+4)” which evaluates exactly as intended.

Example 2:

#define Sum(x, y) (x) + (y);

void main() {

int x = 20;

int y = 15;

int sum = Sum(x, y);

cout << sum << endl;

}

Output:

35

Example 3:

Macro can be expression

#define IsXGreaterThanY(x, y) {if ((x) > (y)) (x) = (y);}

void main() {

int x = 20;

int y = 15;

IsXGreaterThanY(x, y);

cout << x << endl;

cout << y << endl;

}

Output:

15

15

References:

http://www.ebyte.it/library/codesnippets/WritingCppMacros.html#2

http://en.wikipedia.org/wiki/C_preprocessor

2 thoughts on “MACROS

  1. thanks alot i have a question
    “When the compiler encounters a previously defined macro, it first isolates its actual arguments, handling them as plain text strings separated by commas. It then parses the tokenstring, isolates all occurrences of each dummy-argument symbol and replaces it by the actual argument string.”
    why the compilr do this?!!

  2. @Rehab,
    The compiler do this to replace the MACRO parameters with actual arguments. It’s juts like substitution: you have equation 3x+y^2 let parameter be x and y; arguments 1 and 2. So when we substitute here we get (3*1) + (2^2). This is exactly what compiler do

    Thanks,,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s