我想通过使用宏的旧值重新定义宏来改变某些代码的工作方式。但是,由于宏似乎被评估的方式,它对我不起作用。我想要的是立即评估#define
中的宏,以便像
#define A B
将A
定义为B
时#define
的值,并且不会受到B
重新定义的影响。
此示例有效:
// in a header somewhere, can't change this
#define A 1
// wrapper code to replace the number with a run-time expression
#define OLD_A 1
#define NEW_A 42
#undef A
bool flag = false;
#define A ( flag ? NEW_A : OLD_A)
// user code, don't want to change this
//
#include <stdio.h>
main()
{
flag = false;
printf("A is %d\n",A);
flag = true;
printf("A is %d\n",A);
}
输出(按预期):
1$ ./cpptest
A is 1
A is 42
但是,如果我将OLD_A
的定义更改为A
,则无法编译。
// in a header somewhere, can't change this
#define A 1
// wrapper code to replace the number with a run-time expression
#define OLD_A A /// <------ here
#define NEW_A 42
#undef A
bool flag = false;
#define A ( flag ? NEW_A : OLD_A)
// user code, don't want to change this
//
#include <stdio.h>
main()
{
flag = false;
printf("A is %d\n",A);
flag = true;
printf("A is %d\n",A);
}
构建失败:
$ make cpptest
icpc cpptest.cpp -o cpptest
cpptest.cpp(19): error: identifier "A" is undefined
printf("A is %s\n",A);
^
我理解这是设计代码可维护的一种可怕方式,但这是一次性旧版本的补丁,在这种情况下它对我有意义,因为它需要对其他工作代码的更少更改。
答案 0 :(得分:0)
这个答案只涉及“为什么它不起作用?”部分问题。
关于“如何?”的部分可能需要你放弃使用宏的旧定义的意图;因为我认为问题的根源。
预处理器宏与变量的工作方式不同
变量具有价值,并不关心它们是如何得到它的
预处理器宏扩展到它们的定义,
不是定义时定义的价值。
那么在您遇到问题的情况下会发生什么:
// in a header somewhere, can't change this
#define A 1
“A”被定义为“1”,稍后会被忽略。
// wrapper code to replace the number with a run-time expression
#define OLD_A A /// <------ here
“OLD_A”被定义为“A”,当前将分两步扩展为“1”。
#define NEW_A 42
#undef A
“A”未定义,预处理器停止知道它为“1”。
bool flag = false;
#define A ( flag ? NEW_A : OLD_A)
“A”被定义为“(标志?NEW_A:OLD_A)”
目前将扩展为“(flag?NEW_A:A)”,
其中“A”(以某种方式)没有递归扩展(这也无济于事。)
// user code, don't want to change this
#include <stdio.h>
main()
{
flag = false;
printf("A is %d\n",A);
编译器看到:'printf(“A is%d \ n”,(flag?NEW_A:A));'。
flag = true;
printf("A is %d\n",A);
编译器看到:'printf(“A is%d \ n”,(flag?NEW_A:A));'。
}
您是否尝试仅预处理文件,而不是编译?
这导致我的解释得到支持
(在我删除了包含后,使用gcc,这个实验不需要;也从输出中删除了一些无用的行):
MinGW\bin\gcc -E cpptest.cpp
bool flag = false;
main()
{
flag = false;
printf("A is %d\n",( flag ? 42 : A));
flag = true;
printf("A is %d\n",( flag ? 42 : A));
}
至少在我看来,你对“可怕的设计”是正确的。但实际上,有时外部情况会阻止良好的设计。而那些外部情况通常以“你选择的货币/货币/货币”结尾 在这种情况下,情况需要绕道而行,“不应改变具有古老和非常好的测试状态的代码”。这是一个很好的理由 也许你可以说服决策者编辑(它会用动态的东西代替当前的完全静态宏“A == 1”)也不会听从那个要求。在此之后,测试状态(可能基于代码覆盖率等)将非常无效。