【问题标题】:C preprocessor get option list with concatenationC预处理器获取带有连接的选项列表
【发布时间】:2014-12-19 12:04:20
【问题描述】:

我想使用 C 预处理器生成一个依赖于其他编译选项的选项列表。

(或者我可以问我如何将多个字符串连接到一个定义中?)

这里我有一个示例(avr-gcc),但它不起作用:

// C preprocessor get option list with concatenation

#include <stdint.h>

// #define CompileOption1 1        // first compile option
#define CompileOption2 1    // second compile option

static char options[20] = " ";    // string of options

/**********************************************************/
void exec_command (uint8_t opt) {
    switch (opt) {
    #define MAIN_COMMAND "FirstDefinition"
#ifdef CompileOption1
        case 'b':
        #define MAIN_COMMAND (MAIN_COMMAND ## "b")
            break;
#endif
#ifdef CompileOption2
        case 't':
        #define MAIN_COMMAND MAIN_COMMAND ## t
            break;
        case 'u':
#endif
        case 's':
//         #define MAIN_COMMAND (MAIN_COMMAND ## "s")
            break;
        case 'v':    
//         #define MAIN_COMMAND (MAIN_COMMAND ## v)
            break;
        case 'r':
//         #define MAIN_COMMAND "Blabla"
            break;
    }
//     #define MAIN_COMMAND "Testomat"
    strcpy(options, MAIN_COMMAND);
}

/**********************************************************/
int main(void) {

    while(1) {
        exec_command('v');
//         doing something with the options here
    }
} 

我想获取保存在字符串中的正确“选项”列表。

编译显示这些错误:

main.c: In function ‘exec_command’:
main.c:21:0: warning: "MAIN_COMMAND" redefined [enabled by default]
main.c:13:0: note: this is the location of the previous definition
main.c:36:2: warning: implicit declaration of function ‘strcpy’ [-Wimplicit-function-declaration]
main.c:36:2: warning: incompatible implicit declaration of built-in function ‘strcpy’ [enabled by default]
main.c:36:1: error: ‘MAIN_COMMANDt’ undeclared (first use in this function)
main.c:36:1: note: each undeclared identifier is reported only once for each function it appears in

如您所见,我尝试了许多不同的连接方式,但都没有奏效。

也许还有另一种更好的方法来生成这样的字符串?

【问题讨论】:

  • 没有条件#defines。至于隐式函数声明警告,strcpy 声明在 string.h 标头中。
  • 我认为宏无法实现您想要的,因此您可能需要发布另一个问题。
  • 是的 - 我认为这也是“几乎可能”。当然,当我简单地将字母添加到代码中的变量时,它会起作用。但这每次都会执行,并且只传递一个静态字符串。那么将没有使用预处理器的巧妙解决方案。我必须返回一个静态字符串,每次我都必须在源代码中手动更改它。

标签: c gcc c-preprocessor avr-gcc


【解决方案1】:

我认为你需要的代码更像是:

#define B_OPT
#define T_OPT
#define S_OPT
#define V_OPT

void exec_command(uint8_t opt)
{
    switch (opt)
    {
    #define MAIN_COMMAND "FirstDefinition"
#ifdef CompileOption1
    case 'b':
        #undef  B_OPT
        #define B_OPT "b"
        break;
#endif
#ifdef CompileOption2
    case 't':
        #undef  T_OPT
        #define T_OPT "t"
        break;
    case 'u':
#endif
    case 's':
        #undef  S_OPT
        #define S_OPT "s"
        break;
    case 'v':    
        #undef  V_OPT
        #define V_OPT "v"
        break;
    …
    }
    strcpy(options, MAIN_COMMAND B_OPT T_OPT S_OPT V_OPT);
#undef B_OPT
#undef T_OPT
#undef S_OPT
#undef V_OPT
}

我不确定你是否也会#undef MAIN_COMMAND。一方面,最后四个#undef 操作是不必要的。您也可以根据需要重新定义 MAIN_COMMAND 的值;具体要求不清楚。

关键是要为要连接成最终字符串的组件定义宏值,然后依靠字符串连接将相关部分组成一个字符串。

我并不完全相信您尝试做的是一个好主意,但我认为这是实现您似乎想要的一种方法。

【讨论】:

  • 不应该先将*_OPT 宏定义为空(或在#else 子句中)?
  • @Jens:是的——谢谢你的提示。请参阅修改后的代码。我认为使用#else 会使事情变得更加冗长。
【解决方案2】:

你需要 2 个宏一个

#define MAIN_COMMAND "FirstDefinition"

然后

#define MAKE_COMMAND(command) MAIN_COMMAND#command

你可以阅读here了解更多信息,使用它你需要这样做

const char *command;
case t:
    command = MAKE_COMMAND(t);
    break;

在你的函数结束时,假设你已经声明了options并且它适合生成的字符串,做

strcpy(options, command);

【讨论】:

  • 别忘了#include &lt;string.h&gt; 取消隐式声明警告。
  • 谢谢 - 第二个宏中有一个 # 到很多。它现在编译。但是当我查看编译结果时,我看到了这个(0 终止):FirstDefinitiont FirstDefinitions FirstDefinitionv FirstDefinitionr 而不是FirstDefinitiontsvr
猜你喜欢
  • 2011-04-22
  • 2012-03-28
  • 2015-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多