As far as I know you are not allowed to use #define to replace keywords in the language, and that may cause problems when defining a compatibility macro.
Mostly true (C23 6.4.2.1/6). There is an explicit exception for keywords whose names begin with a double-underscore or with an underscore and a capital letter. (C23 6.4.2.1/7, as clarified by footnote 80)
Although "not allowed" is not how I would describe it, at least for C. The language spec does not forbid defining a macro whose identifier matches a language keyword of any form. But, subject to the exception described above, it will interpret language keywords as keywords, which are not subject to macro replacement, rather than as identifiers.
I would prefer to use nullptr instead of NULL prior to C23 too because it means that I could write code which compiles in [C++ and all versions of standard C].
This is a noble goal, and, speaking from (pre-C23) experience, a true PITA. The shared subset of C and C++ is large enough to program in, but it is not particularly comfortable. I would suggest that you choose one language to write in, and support the other via binary compatibility instead of source compatibility.
But if you insist, then your other answer shows how you can use language version macros to inform conditional compilation directives, so as to make appropriate decisions about whether to define a nullptr
macro.
On the other hand, as I already covered, it is allowed in C to define a macro with the same name as a keyword -- it is just ineffective. So you could consider just defining nullptr
as a macro unconditionally, or at least for all versions of C. A C23 compiler might be moved to warn about that, but a conforming one should accept it.