There are sort of three possible "values" for an identifier in the preprocessor:
- Undefined: we don't know about this name.
- Defined, but empty: we know about this name, but it has no value.
- Defined, with value: we know about this name, and it has a value.
The second, defined but empty, is often used for conditional compilation, where the test is simply for the definedness, but not the value, of an identifier:
#ifdef __cplusplus
// here we know we are C++, and we do not care about which version
#endif
#if __cplusplus >= 199711L
// here we know we have a specific version or later
#endif
#ifndef __cplusplus // or #if !defined(__cplusplus)
// here we know we are not C++
#endif
That's an example with a name that if it is defined will have a value. But there are others, like NDEBUG, which are usually defined with no value at all (-DNDEBUG
on the compiler command line, usually).