C Identifiers and Keywords
In C, the word is not a keyword, so the declaration is accepted and the variable can be used like any other.
Why a Name That Works in C Can Fail in C++
A program written in C can use almost any word as a variable or function name, as long as the word is not one of the C keywords. Many programmers carry C habits into C++ work, and most of the time nothing goes wrong. Problems appear when a name that is harmless in C happens to be a special word in C++. This article follows that boundary, so that you can read a C program and decide whether it will also compile as C++.
What do you think happens?
Suppose a C program declares an ordinary variable called new and is compiled with a C compiler. The same source file is then handed to a C++ compiler. Which step do you expect to fail, if any, and why?
Reveal answer
The C compiler accepts the declaration, because C has no keyword called new. The C++ compiler rejects the same line, because new already has a meaning in C++.
The question is not really about the variable's value. It is about which words a language has reserved for its own meaning. The same word can be a free name in one language and a special word in the other.
Tracing the Name new Through Two Compilers
Follow the name new step by step. In C, the word is not a keyword, so the declaration is accepted and the variable can be used like any other. When the identical line reaches a C++ compiler, the name is no longer available as an ordinary identifier, and the line is invalid. Nothing about the variable's value has changed. Only the set of words the compiler treats as special has changed.
Accepted by a C compiler. A C++ compiler rejects the declaration of new, because new is a keyword in C++.- int new = 5; declares an ordinary variable named new in C
- return new; uses the same name in an expression
- The C++ compiler stops at the declaration, not at the value 5
int main(void) {
int new = 5;
return new;
}The name new is valid C but invalid C++
int main(void) {
int count = 5;
return count;
}The name count is valid in both C and C++
The fix is to rename the identifier. This is exactly what the source means when it says the program must be modified to make it a C++ program. The renaming touches every use of the name, so the rename must be consistent across the whole file.
Two Groups of C++ Keywords
C++ provides many more keywords than C does. The source lists a large group of words that are keywords in C++ but are not keywords in C. These are not random leftovers. They support features that C++ adds on top of the shared core vocabulary. When a C identifier collides with one of them, the C++ compiler must reject it.
Not every C++ keyword behaves the same way when a C compiler reads it. The first group consists of words that are simply free to use as names in C. The second group consists of words that already have a definition supplied by the C environment, because they are macros defined in standard headers. The diagram below separates these two situations for the words the source names.
The words in the macro group are the ones the source names as keywords in C++ that are macros in C: and, and_eq, bitand, bitor, bool, compl, false, not, not_eq, or, or_eq, true, wchar_t, xor, and xor_eq. Note that this list is about words that are keywords in C++ and macros in C. The words in the free-name group are the ones that C does not treat as keywords at all.
Keywords That Are Macros in C
A macro keyword in C already has a definition before your code is compiled. That definition comes from a standard header. Because of this, the words can be handled with preprocessor tools. The source states that they can be tested using #ifdef, redefined, and so on. The key idea is that the test happens during preprocessing, before the compiler sees the program, so it is a question asked of the preprocessor rather than a run-time check.
If the macro not is defined when the preprocessor reaches this point, compilation stops with the error message. If it is not defined, the lines are skipped and nothing is reported.- #ifdef not asks whether a macro named not is defined
- #error stops compilation with a message when the test succeeds
- #endif closes the conditional block
Because these words already have a definition, redefining them is a deliberate act, and it changes the meaning of the code that follows. The source mentions redefinition as one of the things that can be done with these macros. When you read unfamiliar C code, a preprocessor test or a redefinition is a signal that the word is being treated as a macro rather than as an ordinary name.
Following a Macro Keyword Through the Preprocessor
Deciding Whether a Macro Name Is Safe
A C program contains the line int not = 0; and must also compile as C++. Decide whether the program can keep this name unchanged, and describe the steps you used.
- 1Identify the word
The word not is in the source list of C++ keywords that are macros in C.
- 2Check the C++ status
not is a keyword in C++, so using it as an ordinary variable name is not acceptable when the file is compiled as C++.
- 3Choose a rename
Replace not with a name that is not a keyword in either language, such as
is_off. The name is then valid in both C and C++. - 4Confirm the test
The preprocessor test #ifdef not would have reported that the word was already defined, which is one way to find such collisions early.
The name not must be renamed. A descriptive replacement such as is_off makes the file compile in both languages.
The Status of export in C++
Not every problem word is a keyword. The word export is reserved for future use in C++. A reserved word is an identifier set aside for potential future use. It has no special behavior today, but programs should not depend on it as an ordinary name, because the language may give it a meaning later.
The source also notes that C99 adopted inline, a word that is also a C++ keyword. This shows that the two languages continue to borrow words from each other over time, so a name that is safe in C today may collide with C++ later. The source material available here does not give a full version history for export, so this article describes only its present status as stated in the source.
Mistakes Beginners Make with C++ Keywords
The following mistakes appear when C code is moved into a C++ build, or when a C programmer assumes that every word not used in C is safe in C++.
Common mistake Assuming that a name accepted by the C compiler will also be accepted by the C++ compiler
What it looks likeint new = 5; compiles as C but not as C++Why it failsC++ has many more keywords than C, so a name free in C may be a keyword in C++.
Do this insteadCheck each identifier against the C++ keyword list before relying on the file as valid C++.
Common mistake Renaming only the declaration and not every use of the identifier
Why it failsThe name must be consistent across the file, or the uses will still refer to the old, invalid name.
Do this insteadRename every occurrence of the identifier together.
Common mistake Treating a macro keyword like not as an ordinary variable name
What it looks likeint not = 0;Why it failsnot is already defined in C as a macro from a standard header, and it is a keyword in C++.
Do this insteadUse a different name such as is_off, and test for existing definitions with #ifdef when in doubt.
Common mistake Believing that a reserved word such as export is free to use because it has no special behavior today
Why it failsA reserved word is set aside for future use, so the language may give it a meaning later.
Do this insteadAvoid export as an identifier in C++ code.
Common mistake Forgetting that a name can become a keyword in a later language version, as happened when C99 adopted inline
Comparing the Three Status Types
| Word type | Example | Status in C | Status in C++ | What to do |
|---|---|---|---|---|
| Free name | new | Not a keyword, so valid as a name | Keyword, so invalid as a name | Rename the identifier |
| Macro keyword | not | Macro defined in a standard header | Keyword | Do not use as a name; test with #ifdef if needed |
| Reserved word | export | Not part of the C keyword discussion in the source | Reserved for future use, no special behavior yet | Avoid as a name |
How the three kinds of words differ when a C program is considered for C++ compatibility
The table separates the words by what the compiler does with them, rather than by how they look. Two words that look equally unusual can behave very differently, so the status should be checked for each word individually.
Practice: Make a C Program Safe for C++
A C file declares the variables new, count, and not. The file must also compile as C++. Decide which names must be changed, propose a replacement for each one that must change, and explain which test you would use to find a macro collision.
Hints
- Compare each name with the C++ keyword group and with the macro group in this article.
- The word count is not in the keyword lists given in the source, so it does not need to change.
- The preprocessor test uses #ifdef, and it is run before compilation.
Keeping C and C++ Code Compatible
When a program must compile as both C and C++, check the identifiers early. Look for words in the C++ keyword group and for macro keywords such as not and true. Use the preprocessor test to find collisions, and choose descriptive names that avoid all of the special words in both languages.
Key Takeaways
- C++ has many more keywords than C, so a name that is a free identifier in C can be a keyword in C++ and must then be renamed.
- Some C++ keywords, such as and, not, true, and bool, are macros defined in standard headers in C, and they can be tested with #ifdef and redefined.
- The word export is reserved for future use in C++ and should be avoided as a name even though it has no special behavior yet.
- Checking which words belong to which group is the first step when debugging a C program that must also compile as C++.