请考虑以下代码:
/*
* 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>调用:
$ 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);在翻译阶段4,标识符_x是非保留的.在翻译阶段7,保留标识符_x (用于普通和标记名称空间中具有文件范围的标识符)。由于翻译阶段4先于翻译阶段7,那么在翻译阶段7,标识符_x (当前定义为宏名称)已经被替换列表0所取代,从而使程序无效。
这是否意味着当用户定义的宏(以下划线开头,后面跟着小写字母)与同名的文件范围标识符发生冲突/重叠时,不能保留该文件范围标识符?
发布于 2022-07-24 23:29:45
找到P.J. Plauger的相关引文(重点是后加的):
请记住,用户可以编写以下划线开头的宏,然后是小写字母。这些名称将保留的与实现者重叠,以命名外部函数和数据对象。
因此,答案似乎是“是”。
发布于 2022-07-24 22:05:49
#define宏始终是文本替代。
当然,头文件本身并不是编译好的实体,因此只有在它们是#included时才会对其进行评估。
假设您有一个包含某个非宏标识符*的标头。
在C模块中,您可以将相同的标识符扩展为任意和病态的标识符,然后将头扩展为#define #include。
由于编译器在遇到#define之前遇到了#include,所以冲突标识符头中的所有提及都将被宏的展开所替代。其后果可能是(而且常常是)灾难性的,或者至少很难调试。
标识符是否以下划线开头并不重要。例如,如果您编写#define printf scanf,就会导致混乱!
(*我规定“非宏”只是为了避免如果头重新定义(或试图重新定义)首先定义的宏时会发生的复杂情况。)
发布于 2022-07-25 01:56:40
不允许使用任何保留名称定义宏。这在C标准第7.1.3p2节中有明确的说明。
如果程序在保留标识符的上下文中声明或定义标识符(7.1.4允许的除外)、或将保留标识符定义为宏名称,则行为未定义。
(粗体:我的重点。)
换句话说,在某些阶段-7上下文中保留的每个标识符也保留为宏名称。
https://stackoverflow.com/questions/73102269
复制相似问题