以下C宏是否会导致问题?

以下C宏是否会导致问题?,c,macros,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; }

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

#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代码?或者你看到什么陷阱了吗?

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

int foo(int a, int b), { return a + b; }
这不是有效的函数定义。要解决此问题,必须删除宏定义中的

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


如果您担心原型声明和相应的函数定义会出现分歧,我建议使用适当的编译器标志或工具。请参阅此问题和答案,

查找以下示例,帮助您满足这两项要求:

#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_MACROa,b的第一个宏和MY_MACROa,b的第二个宏

有很多陷阱,我认为这太天真了

从来没有改变语法分析的宏,尤其是在这里添加语法分析的宏;最后。如果没有终止分号,没有人能够理解这样的代码,它在文件范围内具有类似宏的函数调用。 宏需要两个参数。如果第二个参数中的代码块包含一个不受保护的运算符,那么您就完蛋了。 您的第二个变体的右侧应该没有。 这样会好一点

#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_宏应该不会造成任何伤害,但会吃掉;第二种形式

并不是说我建议你使用这种未经测试的东西

您认为这些宏是否足够安全,可以按预期用于各种C代码?或者你看到什么陷阱了吗

不要试图重新发明C语言。阅读您的代码的人将是其他C程序员。你可以期望他们知道C语言,但你不能期望他们知道自制的车库黑客宏语言


努力编写尽可能简单易读的代码。避免复杂,避免混乱。当没有问题需要解决时,不要试图创建解决方案。

我最近确实做了类似的事情,并学会了将代码作为宏参数传递的陷阱

例如,使用第一个宏定义尝试此看似正确的代码:

MY_MACRO(int foo(int a, int b)
,
{
    int c = 1, d = 2;
    return a + b + c + d;
}
)
您很可能会看到一个编译错误—宏的调子只需要2个参数,而您提供了3个参数

发生的情况是,宏是由不关心C语法的预处理器编译的。所以在它的眼里,每一个都是一个参数分隔符。它认为宏的第一个参数是int fooint a,int b,第二个参数{int c=1,第三个参数是d=2;返回a+b+c+d;}

所以从根本上讲,这个故事的寓意是永远不要把代码作为论据传入。大多数宏都希望灵活地编译成if或for语句,例如list_for_

我建议你在你的情况下坚持标准的礼仪。e、 g

#ifndef UNIT_TEST

int foo(...) {
   //actual implementation
}

#else

int foo(..) {
    return 0;
}
#endif

这类代码相当标准:搜索

的配置,为什么要这样做?我怀疑我的第二个\u宏会起作用。在这种情况下,你会想要这个扩展:定义我的\u宏原型、内容原型、内容这是为了什么?让我试着解释一下为什么我需要这个。我需要这个来编写单元测试。比如说,我有两个模块A和B。A模块依赖于B。我想对A进行单元测试。B有一个具有内联函数的头文件。内联函数在头文件中具有定义内容。模块A调用该函数。在单元测试模块A时,我需要能够在模块B头中创建内联函数的模拟版本。但由于它在头文件中有实现,我无法创建该函数的模拟版本。这就是为什么我需要与问题中的宏相似的宏。实际上,我正在试图解决我在问题注释中解释的单元测试问题。@user3472693所以您试图解决的问题是我无法创建函数。这似乎是人为的问题。为什么不呢?为什么它是内联的还是非内联的?编写晦涩难懂的宏通常不是解决任何问题的好办法。如果单元测试比要测试的代码更复杂,那么它是毫无价值的。是的,这是行不通的。我已经纠正了这个问题。我在转换原始源代码时犯了这个错误。如果你真的想这样做,一个or,就像Jens Gustedt的回答一样,可能会起作用。