我有以下定义宏:
#define NHID 5
#define NENT 10
#define NOUT 4
#define NWEIS (NENT + 1) * NHID + (NHID + 1) * NOUT
因此,每当编译器找到" NWEIS"时,它将替换" NEWIS" for"(NENT + 1)* NHID +(NHID + 1)* NOUT"。但这不是我想要的。我希望它取代" NWEIS"通过实际值= 79,无需在内存中声明额外的变量。有没有一个像样的方法呢?
答案 0 :(得分:3)
宏替换主要是 1 一个迭代过程。
在宏替换之后你会得到什么是一个带有常量的表达式。任何体面的编译器都可以折叠这些常量(在编译时评估它们),以便为您提供79
的单个值。
例如,考虑一下程序:
#define NHID 5
#define NENT 10
#define NOUT 4
#define NWEIS (NENT + 1) * NHID + (NHID + 1) * NOUT
int main (void) { return NWEIS; }
这是gcc -E
的预处理器输出:
int main (void) { return (10 + 1) * 5 + (5 + 1) * 4; }
这里是它用gcc -S
生成的相关汇编代码行(返回值放在eax
寄存器中):
movl $79, %eax
话虽如此,由于你有不断的“变量”,对编译器的内联建议,枚举类型等等,所以使用宏的原因很少,因为宏过去非常有用。
当然,我仍然发现自己正在寻找快速代码的宏,但这主要是因为我是一个古老的鳕鱼,在我们甚至有原型之前的C天就已经伪造了: - )
重新考虑使用它们可能是值得的,因为你可以用以下内容替换它:
const int nhid = 5;
const int nent = 10;
const int nout = 4;
const int nweis = (nent + 1) * nhid + (nhid + 1) * nout;
智能编译器应仍然能够在编译时优化计算,并且您很可能会发现调试器中的变量可用于您,这通常不会发生与宏。
1 完整的详细信息可以在C ++ 11标准的16.3 Macro replacement
部分找到。
可以说宏中有#
和##
的某些用法会阻止进一步替换 令牌(前者用字符串字符替换令牌)后者将多个令牌组合成不同的令牌。)
由于你没有使用它们,所以这里无关紧要。
答案 1 :(得分:2)
您使用的宏不会花费额外的内存。你已经实现了你想要的东西。
让我们看一下合理的编译器会做什么。
假设您有此代码。
#define NHID 5
#define NENT 10
#define NOUT 4
#define NWEIS (NENT + 1) * NHID + (NHID + 1) * NOUT
int f()
{
return NWEIS;
}
合理的编译器显然会将其扩展为:
int f()
{
return (NENT + 1) * NHID + (NHID + 1) * NOUT;
}
下一步将是:
int f()
{
return (10 + 1) * 5 + (5 + 1) * 4;
}
由于此算术表达式仅由硬编码数字(常量表达式)组成,因此编译器也可将整个事物视为常量。
int f()
{
return 79;
}
请注意,此函数非常小,合理的编译器会尽力使函数内联。
然而,这样做更为可取:
constexpr int NHID = 5;
constexpr int NENT = 10;
constexpr int NOUT = 4;
constexpr int NWEIS = (NENT + 1) * NHID + (NHID + 1) * NOUT;
答案 2 :(得分:1)
只需使用
const int NHID = 5;
const int NENT 10;
const int NOUT 4;
const int NWEIS = (NENT + 1) * NHID + (NHID + 1) * NOUT;
一个优秀的优化器将在编译时替换这些值,而不是将任何变量放在内存中,除非你做了一些事情,比如取其地址。然后你就得到了C ++的类型安全和范围,没有宏观的恶意。
(大写字母名称按照惯例为宏保留,因此您可能需要稍微重命名)