#ifndef NULL
#define NULL NULL
#endif
This code compiles in gcc with no warnings/errors. Can someone explain what the preprocessor is doing here?
#ifndef NULL
#define NULL NULL
#endif
This code compiles in gcc with no warnings/errors. Can someone explain what the preprocessor is doing here?
It's normal:
#ifndef JON_SKEET
#define JON_SKEET JON_SKEET
#endif
This compiles too. This is because the preprocessor simply does mindless replaces. What it replaces and what it replaces with don't need to be valid identifiers.
Think of it like this: open your editor's Search & Replace window and type in "NULL" in both the Replace
and Replace with
fields. It won't give any error or warning and it will "work", even though it actually doesn't do anything. The preprocessor does the same thing.
Obviously when you try to use it:
'JON_SKEET' undeclared (first use in this function) (Each undeclared identifier is reported only once for each function it appears in.)
Anywhere the compiler sees the text "NULL" it will replace it with the text "NULL". It's like doing a search-and-replace in your code for "NULL" and replacing with "NULL". Not illegal, just weird :)
Clearly this isn't being used as a macro, it's being used as a compilation flag. Are there other areas of the code where you see #ifdef NULL
or #ifndef NULL
?
It is very strange to use "NULL", specifically, as such a flag, but I've seen stranger (#define TRUE FALSE
)...
The only possible reason for doing this would be to do it before including header files which themselves do something like
#ifndef NULL
#define NULL (void *)0
#endif
This would then stop the NULL from being defined like that.
In answer to the question of what the preprocessor is doing:
Unless there's preceding code that undefs NULL, it's skipping the #define NULL NULL
completely. NULL is almost certainly already defined. In C++, the use of 0 is preferred due to C++'s tighter type-checking. If you must use NULL, it's best to declare const int NULL = 0;
(see Section 5.1.1 of Stroustrup).
I've seen cases where code like this brings a value from the compiler namespace ("namespace" in general, not C++ namespace
) to the preprocessor namespace, e.g.:
// In the compiler namespace, not in the preprocessor namespace
static int const FOO = 1234;
// Bring the constant into the preprocessor namespace as well
#ifndef FOO // <---- FOO really is undefined here.
#define FOO FOO
#endif
Really ugly stuff.
Personally I haven't found a use for this sort of thing, but exists nonetheless.
EDIT: While I've seen this, I don't know why it would be useful, other than check if "FOO
" defined as a preprocessor symbol somewhere else in the code; perhaps in dealing with some legacy code. Anyone?