user2684198
user2684198

Reputation: 852

Why is X undefined in this code?

#include <stdio.h>
#define X (Y+4)
#define Y (X+3)
int main(void) {
    printf("%d\n",4*X+2);
    return 0;
}

Error: Undefined symbol 'X'.

Upvotes: 0

Views: 75

Answers (4)

The preprocessor macro X expands to (Y+4). This contains another preprocessor macro Y, so it is expanded to ((X+3)+4). This in turns contains the preprocessor macro X.

There is a feature of the C preprocessor which blocks recursion: if the name of a macro appears during its expansion, it is left alone. This allows definitions like

#define f(x) (LOG("f called"), f(x))

(not very common, but possible). (If it wasn't for that feature, the preprocessor would loop forever in many cases such as this one, which wouldn't be useful.)

At this point, the preprocessor has finished its job, so X would need to be a variable name. Which it isn't, hence the error message.

Upvotes: 1

Keith Thompson
Keith Thompson

Reputation: 263507

Macro expansion does not recursively re-expand the macro name.

Quoting the C standard:

If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file’s preprocessing tokens), it is not replaced. Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced. These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.

X expands to (Y + 4). The preprocessor then attempts to expand Y, but since the expansion of Y refers to X, it doesn't expand it again, leaving the X in place.

This rule avoids infinite recursion in macro expansion (which is what you'd have in your example if this rule were not there).

After macro expansion, the line

printf("%d\n",4*X+2);

resolves to:

printf("%d\n",4*((X+3) +4)+2);

Since X has not been defined in a way that's visible outside the preprocessor, you have a compile-time error.

Upvotes: 5

user1129665
user1129665

Reputation:

If you have gcc, use the -E switch and see the file after preprocessing:

>type example.c
//#include <stdio.h>
extern int printf(const char *s, ...);
#define X (Y+4)
#define Y (X+3)
int main(void) {
    printf("%d\n",4*X+2);
    return 0;
}
>gcc -Wall -E example.c
# 1 "example.c"
# 1 "<command-line>"
# 1 "example.c"

extern int printf(const char *s, ...);


int main(void) {
    printf("%d\n",4*((X+3)+4)+2); // see X?
    return 0;
}

>

Upvotes: 2

slaadvak
slaadvak

Reputation: 4779

Because X is defined by Y which also reuse X to define itself. Its a circular reference.

Upvotes: 3

Related Questions