Home > Net >  Does non-reserved identifier at translation phase 4 make it impossible to reserve a file scope ident
Does non-reserved identifier at translation phase 4 make it impossible to reserve a file scope ident

Time:07-25

Consider this code:

/* 
 * stdio.h
 * 
 * note: it is an example of a particular implementation of stdio.h
 * containing _x; it is not "my code added to stdio.h"
 */
void _x(void);

/* t627.c */
#define _x 0
#include <stdio.h>

Invocation:

$ gcc t627.c

t627.c:1:12: error: expected identifier or ‘(’ before numeric constant
    1 | #define _x 0
      |            ^
stdio.h:1:6: note: in expansion of macro ‘_x’
    1 | void _x(void);

At translation phase 4 the identifier _x is non-reserved. At translation phase 7 the identifier _x is reserved (for use as identifier with file scope in both the ordinary and tag name spaces). Since translation phase 4 precedes translation phase 7, then at translation phase 7 the identifier _x (currently defined as a macro name) is already replaced by its replacement list 0, invalidating the program.

Does it mean that in cases when the user-defined macro (that begins with an underscore, followed by a lowercase letter) can collide/overlap with the file scope identifier with the same name, such file scope identifier cannot be reserved?

CodePudding user response:

#define macros are always a textual substitution.

Headers, of course, are not compiled entities in their own right, so are only evaluated at the point they are #included.

Let's say you have a header containing a certain non-macro identifier*.

In a C module, you #define that same identifier to expand to something arbitrary and pathological, and then #include the header

Since the compiler encounters the #define before it encounters the #include, all mentions in the header of the colliding identifier will be substituted with the macro's expansion. The consequences can be (and often are) disastrous, or at the very least hard to debug.

It doesn't really matter whether or not the identifier starts with an underscore. If you wrote #define printf scanf, just for instance, that would cause chaos!


(* I stipulate "non-macro" just to avoid the complications of what would happen if the header redefined - or tried to - the macro you defined first.)

CodePudding user response:

You're not allowed to define macros with any of the reserved names. This is stated explicitly in section 7.1.3p2 of the C standard:

If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.

(Boldface: my emphasis.)

To put it another way, every identifier that is reserved in some phase-7 context is also reserved for use as a macro name.

CodePudding user response:

Found a relevant quote from P.J. Plauger (emphasis added):

Remember that the user can write macros that begin with an underscore, followed by a lowercase letter. These names overlap those reserved to the implementor for naming external functions and data objects.

So, the answer seems to be "yes".

  • Related