【问题标题】:How to check if CLI defined MACRO (-DMACRO=) is defined or not如何检查 CLI 定义的 MACRO (-DMACRO=) 是否已定义
【发布时间】:2019-11-19 23:57:54
【问题描述】:

在编译时提供定义时,如何检查是否定义了宏。

我有 Makefile,它在编译示例 C 文件时解析并传递此字符串 ("-DMACRO_TEST=${DEFINED}")。 变量 DEFINED 可能有也可能没有值(0 或非零)。 当变量 DEFINED 本身没有任何值时,我想知道如何检查 MACRO_TEST 是否已定义。这类似于编译 C 文件时传递“-DMACRO_TEST=”。

#include <stdio.h>

#ifdef MACRO_TEST
char msg[] = "MACRO_TEST is defined";
#else
char msg[] = "MACRO_TEST is NOT-defined";
#endif

int main ()
{
    printf("msg = %s\n", msg);
    return 0;
}

命令行输出

$ gcc tmp.c -DMACRO_TEST=0
$ ./a.out
msg = MACRO_TEST is defined
$ gcc tmp.c -DMACRO_TEST=
$ ./a.out
msg = MACRO_TEST is defined

在第二种情况下编译时,我期待它会返回

msg = MACRO_TEST is NOT-defined

【问题讨论】:

  • 它已定义,但值为“empty”,因为 make 用空替换任何缺失的变量。实际上,我不确定编译器是否会将其定义为空,或者在没有赋值时将其定义为默认值 1。您可以使用表达式 MACRO_TEST+0 在 C 代码中探索这一点
  • 有一个重复的问题询问如何区分宏何时未设置、为空、为零或其他任何内容。但我找不到它。
  • @GemTaylor,它对我有用。但是,在我累之前,我认为它会给出编译时错误,因为+ op 需要 2 个参数并且当 MACRO_TEST 设置为“空”时。这将如何运作。

标签: c gcc c-preprocessor


【解决方案1】:

测试宏的一些常见情况:

#ifdef MACRO_TEST
  // MACRO_TEST is defined, whatever its content, even empty
  // for example:
  //   -DMACRO_TEST
  //   -DMACRO_TEST=
  //   -DMACRO_TEST=0
  //   -DMACRO_TEST=1
  //   -DMACRO_TEST=abcd
#else
  // MACRO_TEST is not defined, not even with an empty content
#endif

#if MACRO_TEST // it must not be defined as empty (-DMACRO_TEST= --> error)
  // MACRO_TEST has a non-zero integer value
  // for example:
  //   -DMACRO_TEST
  //   -DMACRO_TEST=1    -- equivalent to -DMACRO_TEST
  //   -DMACRO_TEST=23
#else
  // MACRO_TEST has a zero integer value
  // for example:
  //   (not defined at all, then considered as zero)
  //   -DMACRO_TEST=0
  //   -DMACRO_TEST=what
#endif

【讨论】:

  • 请注意,如果根本没有定义MACRO_TEST#if MACRO_TEST 将起作用;预处理器会将名称转换为0 并适当地评估条件。如果定义了MACRO_TEST,则不能为空(所以-DMACRO_TEST可以;-DMACRO_TEST=不行),必须定义为数值或标识符;它不应该是字符串-DMACRO_TEST='"string"'(注意其中的单引号和双引号!)。
  • @Jonathan Leffler 感谢您的澄清。我相应地编辑了答案。
  • 请注意,如果有宏-Dwhat=1,那么-DMACRO_TEST=what 会将what 扩展为1,等等。我不确定是否需要在答案(也许这个评论就足够了)。这很棘手——预处理器有时会导致复杂的问题。
【解决方案2】:

只需使用#if xxx。未定义的xxx 被预处理器视为零。


#include <stdio.h>

#if MACRO_TEST
char msg[] = "MACRO_TEST is defined";
#else
char msg[] = "MACRO_TEST is NOT-defined";
#endif

int main ()
{
    printf("msg = %s\n", msg);
    return 0;
}

而且,您不必在命令行上提供值,只需-Dxxx 就足够了,编译器/预处理器将假定1

cc -Wall -DMACRO_TEST defined.c

更新。所有四种情况:


#include <stdio.h>

#if MACRO_TEST
char msg[] = "MACRO_TEST is defined and non-zero";
#else
char msg[] = "MACRO_TEST is NOT-defined or zero";
#endif

int main (int argc, char**argv)
{
    printf("%s: msg = %s\n", argv[0], msg);
    return 0;
}

#!bin/sh

cc -Wall defined.c -o x
cc -Wall -DMACRO_TEST defined.c -o xd
cc -Wall -DMACRO_TEST=0 defined.c -o xd0
cc -Wall -DMACRO_TEST=1 defined.c -o xd1

./x
./xd
./xd0
./xd1

rm x xd xd0 xd1

结果:


./x: msg = MACRO_TEST is NOT-defined or zero
./xd: msg = MACRO_TEST is defined and non-zero
./xd0: msg = MACRO_TEST is NOT-defined or zero
./xd1: msg = MACRO_TEST is defined and non-zero

【讨论】:

  • 这几乎是对的,但如果他希望 0 成为有效值,则应该进行多部分测试:#if defined(MACRO_TEST) &amp;&amp; MACRO_TEST != "" 将接受除空字符串之外的所有定义(仅作为示例)。
  • 不,完全正确,避免了三值逻辑。我什至测试过!
  • 字符串比较很可疑,@GaryO。
  • 他希望值为 0 来触发他的“已定义”分支。单独使用#if MACRO_TEST 将导致值 0 进入他的“未定义”分支。
  • 恕我直言,OP 只想拥有两个案例。好的,为了证明我的观点,我会更新答案。 ...
【解决方案3】:

如果您在gcc 命令行中省略任何选项-DMACRO_TEST 或显式添加-UMACRO_TEST(= undefine 宏),则不会定义宏。在这种情况下,预处理器指令#ifdef MACRO_TEST 将为 FALSE,您将得到 ​​p>

char msg[] = "MACRO_TEST is NOT-defined";

#else 分支中。

(假设您没有在代码中定义此宏。)

【讨论】:

  • 我知道我已经概括地提到了 CLI。但最终编译过程是通过使用 Makefile 完成的,我不想更新。
  • @SheetalT 然后在您的问题中显示 Makefile(或生成它的文件)。您如何将宏定义放入您的 Makefile 中?您想区分哪些可能的宏定义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 1970-01-01
相关资源
最近更新 更多