Concepts / C Identifiers and Keywords

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.

  • Programming

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
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.

c
Output
Accepted by a C compiler. A C++ compiler rejects the declaration of new, because new is a keyword in C++.
Notes on the code
  • 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
Before
int main(void) {
    int new = 5;
    return new;
}

The name new is valid C but invalid C++

After
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.

newfree name in Candmacro in Cnotmacro in Cboolmacro in Ctruemacro in Cxormacro in C
Which C++ keywords are free names in C, and which are macros already defined in C?

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.

c
Output
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.
Notes on the code
  • #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
newfree namenotmacro from standard headerexportreserved for future use
Each word maps to its status in C. A word that is a macro can be tested with #ifdef, while a reserved word is set aside but has no special meaning yet.

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

Worked example

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.

  1. 1
    Identify the word

    The word not is in the source list of C++ keywords that are macros in C.

  2. 2
    Check 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++.

  3. 3
    Choose 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++.

  4. 4
    Confirm 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.

Result

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 like
    int new = 5; compiles as C but not as C++
    Why it fails

    C++ has many more keywords than C, so a name free in C may be a keyword in C++.

    Do this instead

    Check 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 fails

    The name must be consistent across the file, or the uses will still refer to the old, invalid name.

    Do this instead

    Rename every occurrence of the identifier together.

  • Common mistake

    Treating a macro keyword like not as an ordinary variable name

    What it looks like
    int not = 0;
    Why it fails

    not is already defined in C as a macro from a standard header, and it is a keyword in C++.

    Do this instead

    Use 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 fails

    A reserved word is set aside for future use, so the language may give it a meaning later.

    Do this instead

    Avoid 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 typeExampleStatus in CStatus in C++What to do
Free namenewNot a keyword, so valid as a nameKeyword, so invalid as a nameRename the identifier
Macro keywordnotMacro defined in a standard headerKeywordDo not use as a name; test with #ifdef if needed
Reserved wordexportNot part of the C keyword discussion in the sourceReserved for future use, no special behavior yetAvoid 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++

MEDIUM

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

Best practice

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++.

Related concepts

More concepts starting with C