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

问题描述 投票:0回答:2

我的问题是: 当 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);
    }
}
c function macros definition
2个回答
1
投票

本来就不是我的宏(我不是作者-作者的名字我忘记了,但有时我会用)


#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();

0
投票

如果你走宏路径(最后的手段),那么至少坚持某种标准化的“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
© www.soinside.com 2019 - 2024. All rights reserved.