很难找到可靠的解决方案。
如果PARA 用于char* 的初始化,那么PARA 可以扩展为PARA_STR(s),后跟+ 和一个依赖于s 的常量表达式0。
例如:
#define PARA_STR(s) "<PARA"#s">"
#define PARA_CONST_EXPR(s) (1 ? 0 : ((void)(s),0))
#define PARA(s) PARA_STR(s) + PARA_CONST_EXPR(s)
代码:
#define ID 10
char *str1 = "Test" PARA(ID);
char *str2 = "Test2" PARA(ID2);
它会产生错误信息:
prog.c:22:27: error: ‘ID2’ undeclared here (not in a function); did you mean ‘ID’?
22 | char *str2 = "Test2" PARA(ID2);
它适用于任何已定义的ID,例如枚举甚至结构。
enum { ID = 5 };
struct { int _; } ID;
char[] 的初始化程序的情况更复杂,更不可靠。
您可以尝试通过添加, 并插入某个指针虚拟对象的新声明来劫持变量的声明。该对象将使用常量0(又名NULL)初始化,该常量表达式由依赖于s(检测未定义标识符)和虚拟变量本身的常量表达式组成,以消除有关未使用变量的警告。
虚拟对象的名称必须是唯一的。
它可以借助__LINE__ 宏或非标准但流行的__COUNTER__ 宏来形成。
经过一些实验我发现:
#define PARA_STR(s) "<PARA"#s">"
#define PARA_CONST_EXPR(s,var) (1 ? 0 : ((void)(s),(void*)&var))
#define CONCAT_(a,b) a ## b
#define CONCAT(a,b) CONCAT_(a,b)
#define PARA_DECL(s, var) *var = PARA_CONST_EXPR(s,var)
#define PARA_UNIQ_VAR CONCAT(para__, __LINE__)
#define PARA(s) PARA_STR(s), PARA_DECL(s, PARA_UNIQ_VAR)
int ID;
char str1[] = "Test" PARA(ID);
char str2[] = "Test2" PARA(ID2); // detected
char *strp1 = "Test" PARA(ID);
char *strp2 = "Test" PARA(ID2); // detected
int main() {
char str3[] = "Test3" PARA(main);
char str4[] = "Test3" PARA(main2); // detected
}
只要在初始化程序的末尾使用PARA,它就可以很好地工作。