1

I'm curious as to what can be used as an identifier for the #define directive in C and/or C++. Is every string token legal?

For example, would the following code compile?

#define EMPTY ;;

for(EMPTY){
  function();
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Nik Vinter
  • 145
  • 10
  • 2
    Identifiers in preprocessor directives are the same as identifiers anywhere else — except that there are no keywords. What you show is legal, but your concern seems to be about the replacement text. The preprocessor is a dumb text replacement machine; it will be quite happy with `;;` as the replacement text. – Jonathan Leffler Feb 18 '20 at 21:20
  • Did you try it? It should work. – R Sahu Feb 18 '20 at 21:20
  • 1
    `#define EVER ;; for(EVER) { ... }` used to be a common idiom – NathanOliver Feb 18 '20 at 21:21
  • related/dupe: https://stackoverflow.com/questions/369495/what-are-the-valid-characters-for-macro-names – NathanOliver Feb 18 '20 at 21:22
  • Note that the rules for the preprocessor in C and C++ are **different** — C++ is more stringent about what you can and cannot do than C is. Dual-tagging questions can lead to confusion. – Jonathan Leffler Feb 18 '20 at 22:20

2 Answers2

4

The rules are more or less the same as for other identifiers. Some names (e.g., those with a leading underscore followed by another underscore or a capital letter) are reserved for the implementation. In C++, names with two successive underscores (anywhere, not just the beginning) are reserved as well.

There is one other proviso that's specific to #define's in C++ (but not C): you're not allowed to re-define a reserved word. So a name like EMPTY is fine, but a name like for or auto would not be.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Thanks, is there a list of reserved names? Or at least a set of well defined rules. EDIT: Nevermind, I didn't know "identifier" had a definition. Thanks. – Nik Vinter Feb 18 '20 at 21:35
  • @NikVinter: I'm at work right now but if I get a chance to, I'll add a list of the precise rules about reserved identifiers sometime tonight. The rules I've given already cover most of them, but there are a few more (e.g., anything starting with "str" or "E", if memory serves). – Jerry Coffin Feb 18 '20 at 21:39
  • Well, I mean, you're not allowed to redefine a reserved word when not using `#define`, either. – S.S. Anne Feb 18 '20 at 21:46
  • 2
    Keywords [§6.4.1](http://port70.net/~nsz/c/c11/n1570.html#6.4.1); Reserved identifiers [§7.1.3](http://port70.net/~nsz/c/c11/n1570.html#7.1.3); No keywords defined as macros when a standard header is included [§7.1.2 ¶4](http://port70.net/~nsz/c/c11/n1570.html#7.1.2p4) — the ban is not total (but you need to be in dire straits to do so); Future library directions](§7.31] (many extra reserved identifiers). Those are the main parts; there may be some others. Note that the majority of the preprocessor 'keywords' are not C keywords per §6.1.4 — the exceptions are `if` and `else`. – Jonathan Leffler Feb 18 '20 at 21:50
  • You are allowed to `#define` keywords, @S.S.Anne, but not when you're about to include a standard header. It's rarely a good idea, but it is allowed. – Jonathan Leffler Feb 18 '20 at 21:51
  • Note also [§6.2.1 Scopes of identifiers ¶1](http://port70.net/~nsz/c/c11/n1570.html#6.2.1p1) — _Macro names and macro parameters are not considered further here, because prior to the semantic phase of program translation any occurrences of macro names in the source file are replaced by the preprocessing token sequences that constitute their macro definitions._ Section [§6.10 Preprocessing directives]((http://port70.net/~nsz/c/c11/n1570.html#6.10] describes the preprocessor as a whole. – Jonathan Leffler Feb 18 '20 at 22:03
  • @JonathanLeffler: Not so. Including any standard header means you can't use a name defined in any standard header. But regardless of including headers: "A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 4, or to the attribute-tokens described in 9.12, except that the names likely and unlikely may be defined as function-like macros (15.6)." (§[macro.names]/2). – Jerry Coffin Feb 18 '20 at 22:06
  • [§6.4.2.1 ¶2](http://port70.net/~nsz/c/c11/n1570.html#6.4.1p2) says: _The above tokens (case sensitive) are reserved (in translation phases 7 and 8) for use as keywords, and shall not be used otherwise. The keyword _Imaginary is reserved for specifying imaginary types._ Preprocessing is [phase 4](http://port70.net/~nsz/c/c11/n1570.html#5.1.1.2). And mentioning sections §9.12 §15.6 suggests you're probably looking at a C++ standard, where the rules may be different; the C standard only has 7 sections plus a number of Annexes (which have letter names, not numbers). _[…continued…]_ – Jonathan Leffler Feb 18 '20 at 22:13
  • _[…Continuation…]_ ***DRAT!!*** The question is tagged with both C and C++. All my quotes are from the **C11** standard (or a late draft thereof). The rules in C++ are different. It really isn't a good idea to dual-tag questions with both C and C++ tags, especially when the rules are different in C and C++. If the question asked "What are the differences in the rules for C and C++ with respect to preprocessing?", it would set nerves atingle. I missed the dual tag. This answer is probably accurate for **C++** (I've not been able to afford a C++14 or C++17 standard, or C18) so I can't check. – Jonathan Leffler Feb 18 '20 at 22:18
  • For the most part, the C++ standard says something along the lines of "Don't mess with defining keywords as macros", which is good advice in C as well as being mandatory in C++. – Jonathan Leffler Feb 18 '20 at 22:23
  • @JonathanLeffler: not exactly the official standard, but (somewhat the same as for C) you can get drafts of the C++ standard from: https://github.com/cplusplus/draft/tree/master/papers. – Jerry Coffin Feb 18 '20 at 22:28
  • Thanks, @JerryCoffin. – Jonathan Leffler Feb 18 '20 at 22:29
0

The syntactic rules for regular identifiers such as names of variables, functions, goto labels, etc... are the same for identifiers used with preprocessor directives.

The C standard has a precise and unique definition for the word identifier, so wherever the word identifier appears in the standard, it is that same thing.

machine_1
  • 4,266
  • 2
  • 21
  • 42
  • I am not sure it can be said to be precise and unique. The definition includes “other implementation-defined characters,” so there is some flexibility (imprecision) to it. Also, the number of significant initial characters in an identifier is implementation-defined. And “identifier” has somewhat different effective meanings at different places in the standard. During preprocessing, anything meeting the pattern in 6.4.2.1 is an identifier. But, after preprocessing, all identifiers identical to keywords are converted to keywords, after which an “identifier” is only a thing that is not a keyword. – Eric Postpischil Feb 18 '20 at 21:56
  • @Eric: I get your point, but am talking about the definition of the word not about its features. – machine_1 Feb 18 '20 at 22:11