C语言 如何使用宏定义通过传递参数修改函数名

y4ekin9u  于 2023-03-28  发布在  其他
关注(0)|答案(2)|浏览(185)

我的问题是:当i=1时

P_COMInit(i) = do { P_SEGi_OUTMODE();}while(0)

但不是

do{P_SEG1_OUTMODE();}while(0)

我怎样才能达到我想要的?
我想用宏定义替换上面的代码

#define P_COMInit(n)
{\
    do{P_COM##n##_OUTMODE();\
    }while(0);\
}\
#define P_SEGInit(n)  do{P_SEG##n##_OUTMODE();}while(0)
 
#define MAX_COM_NUM  2
#define MAX_SEG_NUM    7
 
 
void main(void)
{
    /*  
    P_COM1_OUTMODE();
    P_COM2_OUTMODE();
    P_SEG1_OUTMODE();
    P_SEG2_OUTMODE();
    P_SEG3_OUTMODE(); 
    P_SEG4_OUTMODE();
    P_SEG5_OUTMODE(); 
    P_SEG6_OUTMODE();
    P_SEG7_OUTMODE();*/
    //I want to replace the code above with the below
    uchar i;
    for(i = 1;i <= MAX_COM_NUM;i++)
    {
        P_SEGInit(i);
    }
    for(i = 1;i <= MAX_SEG_NUM;i++)
    {
        P_COMInit(i);
    }
}
blmhpbnm

blmhpbnm1#

最初它不是我的宏(我不是作者-作者的名字被我忘记了,但有时我会使用它)

#define FE_0(WHAT)
#define FE_1(WHAT, X) WHAT(X) 
#define FE_2(WHAT, X, ...) WHAT(X)FE_1(WHAT, __VA_ARGS__)
#define FE_3(WHAT, X, ...) WHAT(X)FE_2(WHAT, __VA_ARGS__)
#define FE_4(WHAT, X, ...) WHAT(X)FE_3(WHAT, __VA_ARGS__)
#define FE_5(WHAT, X, ...) WHAT(X)FE_4(WHAT, __VA_ARGS__)
#define FE_6(WHAT, X, ...) WHAT(X)FE_5(WHAT, __VA_ARGS__)
#define FE_7(WHAT, X, ...) WHAT(X)FE_6(WHAT, __VA_ARGS__)
#define FE_8(WHAT, X, ...) WHAT(X)FE_7(WHAT, __VA_ARGS__)
#define FE_9(WHAT, X, ...) WHAT(X)FE_8(WHAT, __VA_ARGS__)
#define FE_10(WHAT, X, ...) WHAT(X)FE_9(WHAT, __VA_ARGS__)
#define FE_11(WHAT, X, ...) WHAT(X)FE_10(WHAT, __VA_ARGS__)
#define FE_12(WHAT, X, ...) WHAT(X)FE_11(WHAT, __VA_ARGS__)
#define FE_13(WHAT, X, ...) WHAT(X)FE_13(WHAT, __VA_ARGS__)
#define FE_14(WHAT, X, ...) WHAT(X)FE_13(WHAT, __VA_ARGS__)
//repeat more times if more arguments are needed

#define GET_MACRO(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,NAME,...) NAME
#define FOR_EACH(action,...) \
  GET_MACRO(_0,__VA_ARGS__,FE14,FE_13,FE_12,FE_11,FE_10,FE_9,FE_8,FE_7,FE_6,FE_5,FE_4,FE_3,FE_2,FE_1,FE_0)(action,__VA_ARGS__)

#define PCOM(X) P_COM ## X ## _OUTMODE();
#define PSEG(X) P_SEG ## X ## _OUTMODE();
#define CAT(NAME,...) FOR_EACH(NAME,__VA_ARGS__)

// Emit some code
CAT(PCOM,1,2,3,4,3,4,5,6,7)
CAT(PSEG,1,2,3,4,3,4)

它会发出:

P_COM1_OUTMODE();P_COM2_OUTMODE();P_COM3_OUTMODE();P_COM4_OUTMODE();P_COM3_OUTMODE();P_COM4_OUTMODE();P_COM5_OUTMODE();P_COM6_OUTMODE();P_COM7_OUTMODE();
P_SEG1_OUTMODE();P_SEG2_OUTMODE();P_SEG3_OUTMODE();P_SEG4_OUTMODE();P_SEG3_OUTMODE();P_SEG4_OUTMODE();
xmq68pz9

xmq68pz92#

如果你打算使用宏(最后一招),那么至少坚持使用标准化的“X宏”。这些宏在程序中的一个地方收集所有数据,以最大限度地减少重复。易于维护,非常灵活,但很难阅读。
在这种情况下,您可以像这样创建X宏列表:

#define COM_LIST(X) \
  X(1)              \
  X(2)              \

#define SEG_LIST(X) \
  X(1)              \
  X(2)              \
  X(3)              \
  X(4)              \
  X(5)              \
  X(6)              \
  X(7)              \

您可以使用这些列表创建宏常量MAX_COM_NUM等,然后创建一个枚举来“计数”项目的数量。

typedef enum
{
  #define COM_ENUM(n) COM_ENUM_##n,
  COM_LIST(COM_ENUM)
  MAX_COM_NUM
} MAX_COM_t;

typedef enum
{
  #define SEG_ENUM(n) SEG_ENUM_##n,
  SEG_LIST(SEG_ENUM)
  MAX_SEG_NUM
} MAX_SEG_t;

即使你不打算使用它们作为枚举,你现在有一个预处理器项MAX_COM_NUM等于2和一个MAX_SEG_NUM等于7。
如果你喜欢的话,你甚至可以使用X-macros来生成实际的函数(尽管我不推荐这样做,在宏中维护/调试代码并不有趣):

#define CREATE_COM_FUNC(n)       \
  void P_COM##n##_OUTMODE (void) \
  {                              \
    puts(__func__);              \
  }

COM_LIST(CREATE_COM_FUNC)

你可以像这样调用和执行所有的函数:

#define CALL_ALL_PCOM_OUTMODE(n) P_COM##n##_OUTMODE();
COM_LIST(CALL_ALL_PCOM_OUTMODE)

示例:

#include <stdio.h>

#define COM_LIST(X) \
  X(1)              \
  X(2)              \

#define SEG_LIST(X) \
  X(1)              \
  X(2)              \
  X(3)              \
  X(4)              \
  X(5)              \
  X(6)              \
  X(7)              \

// if all functions are of the same type we can get even more generic:
#define CREATE_FUNC(type, n)        \
  void P_##type##n##_OUTMODE (void) \
  {                                 \
    puts(__func__);                 \
  }

// wrapper macros to add the correct prefix:
#define CREATE_COM_FUNC(n) CREATE_FUNC(COM,n)
#define CREATE_SEG_FUNC(n) CREATE_FUNC(SEG,n)

// generate all function definitions:
COM_LIST(CREATE_COM_FUNC)
SEG_LIST(CREATE_SEG_FUNC)

int main(void)
{
  #define CALL_ALL_PCOM_OUTMODE(n) P_COM##n##_OUTMODE();
  COM_LIST(CALL_ALL_PCOM_OUTMODE)

  #define CALL_ALL_PSEG_OUTMODE(n) P_SEG##n##_OUTMODE();
  SEG_LIST(CALL_ALL_PSEG_OUTMODE)
}

输出:

P_COM1_OUTMODE
P_COM2_OUTMODE
P_SEG1_OUTMODE
P_SEG2_OUTMODE
P_SEG3_OUTMODE
P_SEG4_OUTMODE
P_SEG5_OUTMODE
P_SEG6_OUTMODE
P_SEG7_OUTMODE

相关问题