use*_*470 8 c c-preprocessor preprocessor-directive
我希望在我的代码中添加一些条件指令来控制不同的构建,例如:
#if VERSION > 100
/* Compiling here */
#endif
Run Code Online (Sandbox Code Playgroud)
问题是"VERSION"在其他代码中我无法改变.它被定义为一个字符串:
#define VERSION "101"
Run Code Online (Sandbox Code Playgroud)
我想知道是否有某种宏或指令将字符串转换为数字,所以我可以简单地做
#if STRING_TO_NUMBER(VERSION) > 100
/* Compiling here */
#endif
Run Code Online (Sandbox Code Playgroud)
这可能吗?
PS.看来我的描述不太清楚.此要求的主要目的是控制版本分支.例如,在旧版本的100版之前,此程序需要old_function().在此版本之后,所有功能都已迁移到new_function.所以我需要编写这样的代码:
#if VERSION >= 100
old_function();
#else
new_function();
#endif
#if VERSION >= 100
int old_function()
{
...
}
#else
int new_function()
{
...
}
#endif
Run Code Online (Sandbox Code Playgroud)
您可以看到只编译了一个函数.因此,必须在预处理阶段决定条件,而不是在运行时.
棘手的部分是,VERSION被定义为一个字符串,它提出了这个问题.
只要您不需要在 上进行声明或预处理器定义条件VERSION,并且只要您确信该VERSION字符串将只是一个没有前导零的整数(这两者都可能要求过高),如果您的编译器有一个相当有效的常量表达式计算器,您也许可以在编译时执行此操作。
例如,gcc 4.8 将优化掉以下if测试,只留下适当的手臂:
if (strlen(VERSION) > 3 || (strlen(VERSION) == 3 && strcmp(VERSION, "100") > 0)) {
// code if VERSION is at least "101"
} else {
// code if VERSION is "100" or less
}
Run Code Online (Sandbox Code Playgroud)
if通过在未使用的分支中插入对未定义函数的调用,可以轻松证明该语句只有一个分支在编译后幸存下来。使用 gcc(和 clang),并启用优化,不会产生链接器错误:
#include <stdio.h>
#include <string.h>
#define VERSION "101"
// This function is not available for linking
int unknown_function();
// This one is in standard library
int rand();
int main(void) {
int x;
if (strlen(VERSION) > 3 || (strlen(VERSION) == 3 && strcmp(VERSION, "100") > 0)) {
// code if VERSION is at least "101"
x = rand();
} else {
// code if VERSION is "100" or less
x = unknown_function();
}
printf("%d\n", x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在C++11中,有一个更清晰的编译时版本。您可以创建constexpr一个atoi. 结合一些人可能称之为模板的滥用,允许条件声明:
constexpr int const_atoi(const char* num, int accum=0) {
return *num ? const_atoi(num+1, accum*10 + (*num - '0')) : accum;
}
template<bool V_GT_100> struct MoreOrLess_Impl;
template<> struct MoreOrLess_Impl<false> {
// Old prototype
void doit(double x) {...}
};
template<> struct MoreOrLess_Impl<true> {
// New prototype
void doit(long double x) {...}
};
using MoreOrLess = MoreOrLess_Impl<(const_atoi(VERSION) > 100)>;
// ...
// ... MoreOrLess::doit(x) ...
Run Code Online (Sandbox Code Playgroud)
(愚蠢的例子位于http://ideone.com/H1sdNg)