Strange Behaviour of MACros C/C++

Strange behaviour of macros C/C++

Macros are (relatively simple) textual substitutions.

Use parentheses in your definitions (both to enclose the macro itself and the macro arguments):

#define PI (atan(1) * 4)
#define radians(deg) ((deg) * PI / 180)
#define degrees(rad) ((rad) * 180 / PI)

Strange macro behaviour

Your macro does not properly parenthesize the arguments in the expansion:

#define idx(__n__, __i__, __j__) __j__ + __n__*(__i__)

Should be:

#define idx(n, i, j) ((j) + (n) * (i))

Unless you really mean something crazy.

This is a bug, but not one causing your problem. Try fixing the printf format for double to %f instead of %lf. Also make verify the types of j and n, A, epsilon and norm are consistent with the printf formats.

Strange behavior of #define

Preprocessor is just doing simple "find & replace", so this code:

printf("%d",d*d);

changes to

printf("%d",10+10*10+10);

which is 10+100+10 = 120

That's why it's so important to add parens in defines:

#define d (10+10)

Function-like macros and strange behavior

The compiler replaces the macros with exactly what you pass in, verbatim. So you end up with

int a = 5, b = 0;
f((++a) > (b) ? (++a) : (b));
f((++a) > (b+10) ? (++a) : (b+10));

Strange behavior of Macro-expansion

In one case you have + ++ and in the other case you have ++ +. + ++ and ++ + are different streams of tokens. Macro pasting doesn't change tokenization because it's tokens that are pasted.

If you punch your program into a C pre-processor, you'll get this out for that line:

int result = a/d/e*b+ ++c%d;

Notice that the preprocessor had to insert a space because one is mandatory between a + token and a ++ token.

Debug Macro strange behaviour

You are explicitly defining DEBUG in your source file

#define DEBUG

Remove that line so that you are not overriding any definition from your build environment.

strange result on macro expansion

Pass it the -E option (Ex: gcc -E a.c). This will output preprocessed source code.

int main()
{
printf("The value of A is %d\n", - -5);
return 0;
}

So it will introduce a space between - and -5 hence it will be not considered as an decrement operator --, so printf will print 5.

GCC Documentation On Token Spacing provides the Information on Why There is an Extra Space Produced:

First, consider an issue that only concerns the stand-alone preprocessor: there needs to be a guarantee that re-reading its preprocessed output results in an identical token stream. Without taking special measures, this might not be the case because of macro substitution. For example:

 #define PLUS +
#define EMPTY
#define f(x) =x=
+PLUS -EMPTY- PLUS+ f(=)
==> + + - - + + = = =
not
==> ++ -- ++ ===

One solution would be to simply insert a space between all adjacent tokens. However, we would like to keep space insertion to a minimum, both for aesthetic reasons and because it causes problems for people who still try to abuse the preprocessor for things like Fortran source and Makefiles.

For now, just notice that when tokens are added (or removed, as shown by the EMPTY example) from the original lexed token stream, we need to check for accidental token pasting. We call this paste avoidance. Token addition and removal can only occur because of macro expansion, but accidental pasting can occur in many places: both before and after each macro replacement, each argument replacement, and additionally each token created by the # and ## operators.



Related Topics



Leave a reply



Submit