库中的预处理器符号并在使用库时更改符号值

Posted

技术标签:

【中文标题】库中的预处理器符号并在使用库时更改符号值【英文标题】:Preprocessor symbol in library and change the symbols value while using the library 【发布时间】:2019-11-20 13:08:01 【问题描述】:

我的Lib.h 中有一个带有内联函数的库项目:

 static inline void DoStuff(void) __attribute__ ((always_inline));
 static inline void DoStuff(void)
 
 #if(SYMBOL == 1)
     // Stuff
 #elif(SYMBOL == 2)
     // Other stuff   
 #endif

我将我的库编译成libLib.a 并设置SYMBOL=2。现在我在其他项目中使用这个库和标题Lib.h。本项目设置SYMBOL=1,并在本项目中调用DoStuff()#if 指令的哪一部分被执行?我假设编译器将使用#if(SYMBOL == 1) 运行该部分,但我不确定。编译器是怎么处理的?

【问题讨论】:

library into libLib.a and set SYMBOL=2 - 你是怎么做到的?你如何“设置”“SYMBOL=2”?显示代码。 【参考方案1】:

首先,预处理器指令的正确语法是:

static inline void DoStuff(void) __attribute__ ((always_inline));
static inline void DoStuff(void)

#if SYMBOL == 1
    // Stuff

#elif SYMBOL == 2
    // Other stuff   

#endif

如果您愿意,您也可以在比较周围留下括号,但这并不是像常规 if 条件那样绝对必要。

如果您不确定哪些代码部分处于活动状态,您可以使用#warning 使其一目了然:

#if SYMBOL == 1
 #warning Symbol == 1
    // Stuff

#elif SYMBOL == 2
 #warning Symbol == 2
    // Other stuff  

#endif

【讨论】:

好吧,#error 编译会失败,所以#warning 是更好的选择。如果不支持,编译器也会报错,所以和#error不支持的效果几乎一样;) #warning 在我的情况下确实有效,所以我已经验证了我的假设。 带括号的语法没有错,只是不需要。 @thebusybee 我没有声称,但其他部分是错误的(否则,endif 缺失) 是的,但这让我眼前一亮。对不起,噪音。无论如何,您可能想扩展您的答案。 ;-)【参考方案2】:

在 C 中,以 # 开头的行由预处理器预处理,这意味着当你编译它时,编译器会这样读取它(例如,如果 in库 SYMBOL=1:

static inline void DoStuff(void) __attribute__ ((always_inline));
static inline void DoStuff(void)

    //only the stuff that were in the block of SYMBOL=1

当您将代码编译到库中时,它不再知道 SYMBOL。 当您在代码中更改 SYMBOL 时,它只会针对该项目进行更改。 要解决此问题,请在标头中使用宏:

在 DoStuff.h 中:

void __do_stuff1();
void __do_stuff2();
static inline void DoStuff()

    #if SYMBOL==1
        __do_stuff1();
    #elif SYMBOL==2
        __do_stuff2();
    #endif

在 DoStuff.c 中:

void__do_stuff1()...
void __do_stuff2()...

【讨论】:

以上是关于库中的预处理器符号并在使用库时更改符号值的主要内容,如果未能解决你的问题,请参考以下文章

如何防止静态库中的所有符号加载以及为什么在链接静态库时导出相同.o文件中的其他符号进行测试

将导出的符号保存在共享库中

基于 NuGet PackageReference 定义一个 C# 预处理器符号

删除 C# 二进制文件中未使用的预处理器符号

在模块中找不到 (1) 中引用的非法预处理器指令和符号

预处理器指令