我想创建两个宏。其中一个将扩展到功能原型和功能内容,另一个将扩展到仅功能原型。我正在考虑创建以下内容:
#ifdef SOME_CONDITION
#define MY_MACRO(prototype, content) prototype;
#else
#define MY_MACRO(prototype, content) prototype content
#endif
作为示例用法
MY_MACRO(int foo(int a, int b)
,
{
return a + b;
}
)
这些宏似乎工作正常。你认为那些宏是否足够安全,以便它们可以按照预期的方式用于各种C代码?或者你看到任何陷阱?
答案 0 :(得分:4)
第一个主要陷阱,它不起作用。使用第二个宏时,它会创建
int foo(int a, int b), { return a + b; }
这不是有效的函数定义。要解决此问题,您必须删除宏定义中的,
。
我看到的第二个陷阱,通常C程序员不使用这种花哨的宏。当你习惯于阅读C源代码时,这简直令人困惑。
如果您担心分散原型声明和相应的函数定义,我建议使用适当的编译器标志或工具。请参阅此问题和答案,How to find C functions without a prototype?
答案 1 :(得分:2)
我认为存在很多陷阱,它太天真了。
;
。没有人能够理解像文件范围内具有类似函数的宏调用的代码而没有终止分号。,
运算符,那么你就搞砸了。,
。这会更好一点
#ifdef SOME_CONDITION
#define MY_MACRO(prototype, ...) prototype
#else
#define MY_MACRO(prototype, ...) prototype __VA_ARGS__ extern double dummyForMY_MACRO[]
#endif
您必须将其用作
MY_MACRO(int foo(int a, int b), { return a + b; });
所以这至少提供了一些在视觉上更接近C代码的东西(好吧......)并处理中间逗号的问题。未使用的变量dummyForMY_MACRO
应该不会造成伤害,但是"吃掉"第二种形式的;
。
并非我建议您使用此类未经测试的事情。
答案 2 :(得分:1)
您认为这些宏是否足够安全,以便它们能够按预期用于各种C代码?或者你看到任何陷阱?
不要试图重新发明C语言。阅读代码的人将是其他C程序员。你可以期待他们知道C.你不能指望他们知道"家庭酿造的车库 - 黑客 - 宏语言"。
努力编写尽可能简单的代码。避免复杂性,避免混淆。当没有问题需要解决时,不要尝试创建解决方案。
答案 3 :(得分:0)
查找以下帮助您满足两个要求的示例:
#ifdef SOME_CONDITION
#define MY_MACRO(a, b) \
int foo(int a, int b);
#else
#define MY_MACRO(a, b) \
int foo(int a, int b) \
{\
return 0;\
}
#endif
您可以使用第一个宏 MY_MACRO(a,b)和第二个宏作为 MY_MACRO(a,b);
答案 4 :(得分:0)
我实际上最近做了类似的事情并且学习了将代码作为宏参数传递的缺陷。
例如,尝试这个看似正确的代码(使用第一个宏定义):
MY_MACRO(int foo(int a, int b)
,
{
int c = 1, d = 2;
return a + b + c + d;
}
)
当你提供3时,你很可能会看到一个编译错误的东西,只有2个参数。
发生的事情是宏是由预处理器编译的,它不关心C语法。所以在它看来,每个,
都是一个参数分隔符。所以它认为宏的第一个参数是int foo(int a, int b)
,第二个参数是{ int c = 1
,第三个参数是d = 2; return a + b + c + d; }
。
基本上,故事的寓意是“永远不会将代码作为参数传递”。大多数希望以代码方式灵活的宏可以编译成if
或for
语句(例如http://lxr.free-electrons.com/source/include/linux/list.h#L407中的list_for_each
)。
我建议您坚持使用标准#ifdef
ery。 e.g。
#ifndef UNIT_TEST
int foo(...) {
//actual implementation
}
#else
int foo(..) {
return 0;
}
#endif
此类代码非常标准:http://lxr.missinglinkelectronics.com/#linux+v3.13/include/linux/of.h(搜索CONFIG_OF
)