以下C宏会导致问题吗?

时间:2014-04-23 10:50:10

标签: c macros

我想创建两个宏。其中一个将扩展到功能原型和功能内容,另一个将扩展到仅功能原型。我正在考虑创建以下内容:

#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代码?或者你看到任何陷阱?

5 个答案:

答案 0 :(得分:4)

第一个主要陷阱,它不起作用。使用第二个宏时,它会创建

int foo(int a, int b), { return a + b; }

这不是有效的函数定义。要解决此问题,您必须删除宏定义中的,

我看到的第二个陷阱,通常C程序员不使用这种花哨的宏。当你习惯于阅读C源代码时,这简直令人困惑。

如果您担心分散原型声明和相应的函数定义,我建议使用适当的编译器标志或工具。请参阅此问题和答案,How to find C functions without a prototype?

答案 1 :(得分:2)

我认为存在很多陷阱,它太天真了。

  1. 从来没有改变语法分析的宏,特别是在最后添加;。没有人能够理解像文件范围内具有类似函数的宏调用的代码而没有终止分号。
  2. 你的宏确实需要两个参数。如果第二个参数中的代码块包含一个不受保护的,运算符,那么你就搞砸了。
  3. 你的第二个变体肯定不会在右侧有,
  4. 这会更好一点

    #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; }

基本上,故事的寓意是“永远不会将代码作为参数传递”。大多数希望以代码方式灵活的宏可以编译成iffor语句(例如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