如何用C中#define宏中的字符串常量替换函数名
Posted
技术标签:
【中文标题】如何用C中#define宏中的字符串常量替换函数名【英文标题】:How to replace function name with string constant in #define macro in C 【发布时间】:2014-07-15 12:21:21 【问题描述】:我希望使用预处理器指令将函数调用替换为字符串。 像这样的:
#ifdef DEBUG
#define Func1(arg) "Function not supported"
#endif
所以基本上当有人调用这个函数时,我想要一个编译错误,这样这个函数在DEBUG
模式下是不可见的,代替那个,在编译日志中打印以下字符串。
此方法会引发错误。
当func1()
被调用时,还有其他方法可以打印我想要的特定字符串吗?
【问题讨论】:
请澄清“引发错误”。是编译错误吗?运行时错误?在使用站点提供错误描述和代码。 确切的错误是:“错误:表达式必须具有(指向)函数类型”...。此错误在调用此函数的位置引发。 信息有那么重要吗? 【参考方案1】:归档这种行为最明显的方法是使用#error
指令。但是,由于不可能构造“有条件的#error
指令”,我猜下一步是在 C99 中引入的_Pragma
运算符。这是在编译期间产生消息的解决方案:
#include <stdio.h>
#define DEBUG 1
#ifdef DEBUG
#define Func1(arg) _Pragma("message \"Function not supported.\"")
#endif
void (Func1)(int arg)
int main(void)
Func1(1);
Func1(2);
Func1(3);
return 0;
编译(与gcc
):
...
check.c:15: note: #pragma message: Function not supported.
check.c:16: note: #pragma message: Function not supported.
check.c:17: note: #pragma message: Function not supported.
我知道这不是直接的解决方案(这样的消息甚至不被视为警告,所以-Werror
不会改变任何东西),但是你可以使用例如grep
工具或任何其他方法来扫描编译器的输出。
从 GCC 4.8 开始,还有 #pragma GCC error "message"
,这是直接(但不可移植)的解决方案。查看this answer 了解更多信息。例如:
#ifdef DEBUG
#define Func1(arg) _Pragma("GCC error \"Function not supported.\"")
#endif
【讨论】:
我的问题是,我需要在调用函数的地方出现编译错误。在您的解决方案中,将在实际编译函数之前处理预处理器。所以当以顺序方式处理时,预处理器不会执行。 @user3840787:“执行”Func1(arg)
类函数宏的实际位置是main
定义中的Func1(1);
指令。定义宏并不重要,如果没有适当的调用,它不会做任何事情。【参考方案2】:
一种方法是简单地保留函数未定义。这将导致链接时出错。
如果你使用 gcc,你可以使用它的一个扩展,一个函数属性:
#ifndef DEBUG
#define __nodebugonly
#else
#define __nodebugonly __attribute__((error("Function not supported")))
#endif
void Func1(int arg) __nodebugonly;
【讨论】:
对,我在这方面误读了你的问题。因为__debugonly
用词不当,所以我也改了。【参考方案3】:
你可以使用
#error "Function not supported"
中止编译。 但是很明显,当有人可以访问可以删除的源时 - 那么你到底想做什么呢?
如果您不信任这些人提供您的资源,请不要将其提供给他们。 将其链接到 .obj 中,用 .h 定义“接口”,然后只给出它。
【讨论】:
我本可以使用#error... :) 但是在处理预处理器时会立即调用它,而不是在调用函数时。 :( :(以上是关于如何用C中#define宏中的字符串常量替换函数名的主要内容,如果未能解决你的问题,请参考以下文章