#include <iostream>
#define true false
#define false true
int main() {
std::cout << false << true;
}
Why does it output "01"?
As Jerry Coffin notes, you cannot define a macro with a name that is a keyword.
However, we could consider another, similar example, with well-defined behavior and the same result. Consider:
int TRUE = 1;
int FALSE = 0;
#define TRUE FALSE
#define FALSE TRUE
std::cout << FALSE << TRUE;
When you use FALSE
, it is identified as the macro FALSE
and is replaced by that macro's replacement list, which is the single token, TRUE
. That replacement is then rescanned for further macros to replace.
The TRUE
in the replacement is then identified as a macro and is replaced by its replacement list, which is the single token FALSE
. That replacement is again rescanned.
If we continued on rescanning and replacing, we'd end up in an infinite loop, so the C (and C++) preprocessing specifications state that macro replacement never recurses within a replacement list.
Since replacement of FALSE
in this final replacement list would result in recursion, macro replacement stops and we are left with FALSE
, which is the name of an int
with a value of 0
.
Any attempt at re-defining a reserved word gives undefined behavior.
Edit:
§2.11/1: "The identifiers shown in Table 3 are reserved for use as keywords." I won't try to reproduce all of Table 3, but it includes both false and true. It may be open to some question whether this is an absolute prohibition, though, since the same sentence adds: "(that is, they are unconditionally treated as keywords in phase 7)", which suggests that it's possible to re-define keywords this way, since the macros involved would be/are expanded before phase 7.
In this case, however, you've also included <iostream>
, which brings another rule into play (§17.4.3.1.1): "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."
The wording here strongly suggests that there's an intent that if a translation unit didn't include any header, it would be free to re-define a keyword as you've done, but given the presence of the #include <iostream>
, there's no question that you have undefined behavior.
Once you have undefined behavior, there really is no more to say about "why" anything happens -- at that point, the standard is very clear that any behavior is permissible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With