In this article from Guru of the week, it is said: It is illegal to #define a reserved word.
Is this true? I can’t find anything in the norm, and I have already seen programmers redefining new, for instance.

- 5,753
- 72
- 57
- 129

- 12,505
- 10
- 59
- 116
-
1It's definitively possible to use `#define` to change the meanings of reserved words. In fact it's often been used in [The International Obfuscated C Code Contest](http://www.ioccc.org/) entries. It's possible because macros defined by `#define` are replaced by a separate program before the actual C compiler runs. – Some programmer dude Feb 02 '12 at 08:53
-
sure they did not overload the new operator? since the preprocessor runs first the problemwith re-"#define"-ing keywords is that you replace keywords with your replace string, code not expecting this will most likely be broken there after. It is generally a bad idea to do so, why would you want to do that anyway? – ted Feb 02 '12 at 08:53
-
@ted: the idea is to redefine the new keyword in a source file so as to call a platform-specific implementation: `#define new newMac` on Macintosh and `#define new newPc` on PC. In other translation units, the corresponding functions will define platform-specific memory allocators. I guess the idea was to continue using `new` everywhere while having a platform-specific behaviour when it was not possible to rename every call to new. – qdii Feb 02 '12 at 09:06
-
1Back in the day, we used to fix Visual Studio 6's incorrect scoping of variables declared in a `for` loop with `#define for if (false) else for` – Jack Aidley Mar 04 '13 at 10:13
-
What do you mean by "I have already seen programmers redefining new"? Have you seen an example of this using `#define`? Or are you referring to overloading the `new` operator? These are two very different things. – Code-Apprentice Jun 25 '13 at 02:17
-
@MonadNewb I have already seen `#define new newPS3`. Video game industry can be a bit like a zoo. – qdii Jun 25 '13 at 13:53
5 Answers
17.4.3.1.1 Macro names [lib.macro.names]
1 Each name defined as a macro in a header is reserved to the implementation for any use if the translation unit includes the header.164)
2 A translation unit that includes a header shall not contain any macros that define names declared or defined in that header. Nor shall such a translation unit define macros for names lexically identical to keywords.
By the way, new
is an operator and it can be overloaded (replaced) by the user by providing its own version.

- 228,013
- 71
- 433
- 510

- 202,538
- 53
- 430
- 533
-
8Note that that rule only applies to sources which include a standard header. It's perfectly legal to redefine a keyword if the translation unit doesn't include a standard header. (It doesn't do much for the readability of the code, however.) – James Kanze Feb 02 '12 at 08:58
-
1So I’m allowed to `#define new` so long as my translation unit includes no headers :P ? @JamesKanze: why **standard** headers? – qdii Feb 02 '12 at 09:05
-
-
2@victor - The language allows the compiler to *know* what is in each standard header, so it doesn't have to recompile them each time. Therefore you are forbidden to change them by redefining some of the words in those headers. What you do to your own headers is up to you! – Bo Persson Feb 02 '12 at 09:32
-
@BoPersson In this case, it's more a case of the standard allowing the implementation to use normal C++ code in the standard headers. Can you imagine what might happen if you did `#define while for` before including `
`. The standard also requires certain "functions" to be macros, so even redefining a keyword after the inclusion of the header could impact things. – James Kanze Feb 02 '12 at 09:47 -
@ted: I was just referring to the fact that this text extract talks about "headers" in a more general sense than just "standard" headers. I wanted to know why James had stated that this only applied to sources that included standard headers. – qdii Feb 02 '12 at 10:08
-
1In the C++03 standard, the term _header_ is defined in **17.4.1.2 Headers [lib.headers]** with: "The elements of the C++ Standard Library are declared or defined (as appropriate) in a _header_." This does not correspond with what we normally consider to be headers (.h files). The standard has no notion of the difference between a .cpp file and a .h file; they are all defined as _source files_. – Joseph Mansfield Feb 02 '12 at 10:43
-
For C++11, the definition is similar: "Each element of the C++ standard library is declared or defined (as appropriate) in a header." This time it is clear that each element can be in different headers. However, the **[macro.names]** uses the term "standard library header" to be clear. – Joseph Mansfield Feb 02 '12 at 10:54
The corresponding section from C++11:
17.6.4.3.1 Macro names [macro.names]
1 A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
2 A translation unit shall not #define or #undef names lexically identical to keywords.
Paragraph 1 from C++03 has been removed. The second paragraph has been split in two. The first half has now been changed to specifically state that it only applies to standard headers. The second point has been broadened to include any translation unit, not just those that include headers.
However, the Overview for this section of the standard (17.6.4.1 [constraints.overview]) states:
This section describes restrictions on C++ programs that use the facilities of the C++ standard library.
Therefore, if you are not using the C++ standard library, then you're okay to do what you will.
So to answer your question in the context of C++11: you cannot define (or undefine) any names identical to keywords in any translation unit if you are using the C++ standard library.

- 108,238
- 20
- 242
- 324
-
What's the definition of using the C++ standard library? For example, does the program `int main() {}` use the C++ standard library? I'm asking this because [\[basic.start.main\]/5](https://timsong-cpp.github.io/cppwp/n4659/basic.start.main#5) mentions `std::exit`. – L. F. Nov 09 '19 at 09:53
They're actually wrong there, or at least doesn't tell the whole story about it. The real reason it's disallowed is that it violates the one-definition-rule (which by the way is also mentioned as the second reason why it's illegal).
To see that it's actually allowed (to redefine keywords), at least if you don't use the standard libraries, you have to look at an entirely different part of the standard, namely the translation phases. It says that the input is only decomposed into preprocessor tokens before preprocessing takes place and looking at those there's no distinction between private
and fubar
, they are both identifiers
to the preprocessor. Later when the input is decomposed into token
the replacement has already taken place.
It has been pointed out that there's a restriction on programs that are to use the standard libraries, but it's not evident that the example redefining private
is doing that (as opposed to the "Person #4: The Language Lawyer" snippet which uses it for output to cout
).
It's mentioned in the last example that the trick doesn't get trampled on by other translation units or tramples on other. With this in mind you should probably consider the possibility that the standard library is being used somewhere else which will put this restriction in effect.

- 13,817
- 1
- 35
- 57
Here's a little thing you can do if you don't want someone to use goto's. Just drop the following somewhere in his code where he won't notice it.
#define goto { int x = *(int *)0; } goto
Now every time he tries to use a goto statement, his program will crash.

- 407
- 4
- 15
-
1@JackAidley yeah, but have you asked yourself what makes it funny? The answer is that humans are sadistic creatures and that's the scare part... +1 for pointing human nature. – mip Dec 26 '14 at 16:52
-
5
-
3If you think `goto` is bad, just like that, you should not be writing programs, if you could convince me that one must never use `goto` I will be very surprised. – Iharob Al Asimi Apr 18 '15 at 20:50
-
1@iharob Agreed. Finite state machines come to mind as a potentially good use of `goto` – chbaker0 Apr 18 '15 at 21:03
-
Your statement that it'll *always* crash the program is not true. Hence, a real programmer should never do this. On many compilers that statement will be optimized out and the program will not crash. The compiler can easily optimize out everything inside the block statement, because x is unused anyway. Even if it's not optimized out, it's still *undefined behaviour*, not a guaranteed crash. – Amy Apr 18 '15 at 21:12
-
If you want to punish the use of `goto`, creating an unreliable runtime error is a silly way to do it. If you must do this, make it a compile-time error: `#define goto @` – Keith Thompson Apr 18 '15 at 21:14
-
@chbaker0: Yes, but `goto` isn't necessarily the best way to implement a finite state machine; a switch statement in a loop makes the current state explicit. See [this answer](http://programmers.stackexchange.com/a/133523/33478) for more discussion of when `goto` is appropriate. – Keith Thompson Apr 18 '15 at 21:17
-
@Amy: You are correct, he should have written: `#define goto { int x = *(int volatile *)0; } goto`. Yet it will expand as 2 statements and cause syntax errors in `if (xx) goto yy; else ...` . He deserves more down votes for crippling the language. – chqrlie Apr 18 '15 at 22:45
It's not as far as I'm aware illegal - no compiler I've come across yet will generate an error if you do
#define true false
#defining
certain keywords are likely to generate errors in compilation for other reasons. But a lot of them will just result in very strange program behaviour.

- 9,244
- 3
- 33
- 61
-
Such definitions are likely to cause problems with the standard library. – James Kanze Feb 02 '12 at 09:49
-
Possibly, on some parts. The problem I have is that though it's illegal, there doesn't seem to be any requirement for the compiler to issue a diagnostic. And depending on which bits of the standard library you use and where you put that #define in your code, the program could compile fine. – Tom Tanner Feb 02 '12 at 11:01
-
2Like so many things, it's undefined behavior. It wouldn't be difficult for a compiler to detect it, and cause a compile time error, but I don't know of any that do. – James Kanze Feb 02 '12 at 11:06
-