在“#if”宏上请求预定义值作为浮点(或字符串)

Ron*_*Ron 0 c

我想以#if预定义变量的浮点(或字符串)值为条件。

正如我所见,如果预定义变量的值是整数,则#if效果很好。但是,如果它是浮点数或字符串,则 if 无法按预期工作。

例如:

#define _VER_ = 103
#if _VER_ == 103
//Do somthing
#endif
Run Code Online (Sandbox Code Playgroud)

上面的代码按预期工作,#if根据_VER_值变为活动/不活动。但是,如果_VER_将该值设置为1.0.3或 则"1.0.3"不会#if按预期工作。

例如:

#define _VER_ = 1.0.3

#if _VER_ == 1.0.3
//Do somthing
#endif
Run Code Online (Sandbox Code Playgroud)

或这个:

#define _VER_ = "1.0.3"

#if _VER_ == "1.0.3"
//Do somthing
#endif
Run Code Online (Sandbox Code Playgroud)

两个代码示例均未按预期工作,无论值#if如何,它们都保持不活动状态_VER_

如何使其正常工作?

Aco*_*gua 6

预处理器根本无法进行字符串比较,并且#if标准也不支持指令中的浮点值。但即使他们比较浮点数,由于舍入问题始终很关键(请记住,您甚至无法准确地表示许多像 0.1 这样的简单数字,因为它们在二进制中是周期性的),请参见例如此处此处,因此您无法比较也可以安全地浮点(很可能这就是不支持它们的原因......)。

\n

不过,您可以做的是拥有三个不同的整数值:

\n
#define MAJOR    1\n#define MINOR    0\n#define REVISION 3\n
Run Code Online (Sandbox Code Playgroud)\n

现在您可以分别对这些单个值进行比较,例如:

\n
#if MAJOR > 1 || MAJOR == 1 && MINOR > 0\n// anything after 1.0.x \n
Run Code Online (Sandbox Code Playgroud)\n

您还可以做的就是通过适当移动这些值将它们组合成一个整数值,例如

\n
#define VERSION MAKE_VERSION(MAJOR, MINOR, REVISION)\n#define MAKE_VERSION(X, Y, Z) MAKE_VERSION_(X, Y, Z)\n// intermediate step necessary to resolve the version parts correctly\n#define MAKE_VERSION_(X, Y, Z) (X ## lu << 16 | Y ## lu << 8 | Z ## lu)\n
Run Code Online (Sandbox Code Playgroud)\n

添加lu后缀:long标准保证足够大,以便移位 16 位将适合该类型(这不能保证int!)。您可以尝试使用其他偏移量以使结果适合 int,然后省略后缀(例如移位 8 或 12 而不是 16)或允许更多子版本(例如移位 20 而不是 16)。

\n

乘以 10000 和 100 也能达到目的,并产生更多人类可读的版本号(至少以十进制表示)。

\n

最后,您可以通过另一个宏创建版本字符串:

\n
#define VERSION_STRING MAKE_VERSION(MAJOR, MINOR, REVISION)\n#define MAKE_VERSION(X, Y, Z) MAKE_VERSION_(X, Y, Z)\n// intermediate step needed for correct stringification\n#define MAKE_VERSION_(X, Y, Z) #X "." #Y "." #Z\n
Run Code Online (Sandbox Code Playgroud)\n

边注:

\n
#define _VER_ = 103\n
Run Code Online (Sandbox Code Playgroud)\n

显然是错误的,原因有二:

\n
    \n
  1. 预处理器除了纯文本处理之外什么也不做,它不知道任何 C 代码。赋值符号 ( =) 将包含在您使用它的任何地方的文本替换中(因此#if _VER_ == 103将扩展为#if = 103 == 103)。
  2. \n
  3. 以下划线开头后跟大写字符的标识符被保留,使用它们会导致未定义的行为(注意:在任何地方 \xe2\x80\x93 也带有两个后续下划线 \xe2\x80\x93 的标识符)。
  4. \n
\n

  • “#if”预处理器指令中的浮点问题与舍入无关,而是根本不支持浮点。根据标准,控制表达式必须是*整数常量表达式*。 (3认同)