tags:

views:

518

answers:

7
+5  Q: 

#define NULL NULL

#ifndef NULL
#define NULL NULL
#endif

This code compiles in gcc with no warnings/errors. Can someone explain what the preprocessor is doing here?

+4  A: 

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.)
Andreas Bonini
Yes, but blocks like that generally imply that the *fact that the symbol is defined* is what matters. Pretty strange to be doing that for NULL.
Aaronaught
Not really, it's not a requirement.
Andreas Bonini
+17  A: 

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 :)

Doug T.
I think it's important to note that it's almost certainly not doing this unless NULL is undefined. NULL is usually defined, so this block probably doesn't do anything.
Adam
A: 

doesn't that simply define NULL as the character sequence "NULL" ?

No. It would be `#define NULL "NULL"`
Andreas Bonini
Be careful when you say character sequence and use quotes, since it might seem you are referring to a c-string character array `"NULL"`.
catchmeifyoutry
he was, because the question was...
dicroce
+1  A: 

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)...

Aaronaught
+7  A: 

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.

Artelius
Sir, I approve of your avatar. I have not thought of Lemmings in a long time.
sheepsimulator
Doesn't that just raise the even more mysterious question of why you'd want to stop NULL from being defined in some other header?
Aaronaught
Well, beats me :)
Artelius
This question is also tagged C++, and in §5.1.1 of his book, Stroustrup recommends the following definition: `const int NULL = 0;`
Greg Bacon
+1  A: 

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).

Adam
+2  A: 

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?

Void
Hmm, I thought I had a use there for a moment, but then I realised it was wrong. If FOO is already defined, then it will have been replaced in the line `static int const FOO = 1234;`. I have no idea why you would be prepared to carry on under those conditions. `#define FOO FOO` potentially makes sense, as you say, if you're replacing a macro with a constant but don't want to change some old code that checks for it being defined. But letting FOO be defined to something else when you're defining constant FOO sounds like trouble to me.
Steve Jessop
@Steve: Agreed. Such code is certainly hinky.
Void