我试了一个多星期都没有成功。
我正在创建两个处理器之间的日志接口,我需要有关定义自动宏的帮助。
我什么意思?
假设我有一个定义为LOGGER_MSG_ID_2的日志消息,它接受uint8和uint16类型的两个参数。
我有一个枚举定义为:

typedef enum{
    PARAM_NONE,
    PARAM_SIZE_UINT8,
    PARAM_SIZE_UINT16,
    PARAM_SIZE_UINT32
}paramSize_e;

因此LOGGER_MSG_ID_2将有一个位图定义为:
#define LOGGER_MSG_ID_2_BITMAP   (PARAM_SIZE_UINT16 << 2 | PARAM_SIZE_UINT8)

这个位图是1字节大小,所以最大的参数数是4。
稍后,我有一个列表,根据消息ID定义所有参数类型:
#define ID_2_P0_TYPE                                uint8  // first parameter
#define ID_2_P1_TYPE                                uint16 // 2nd parameter
#define ID_2_P2_TYPE                                0      // 3rd parameter
#define ID_2_P3_TYPE                                0      // 4th parameter

如前所述,我有4个参数的限制,所以我想定义它们,让宏决定是否使用它们我把它们定义为0,但它可以是任何有效的。
我还有其他宏使用位图来获取所有类型的属性,比如参数的数量和消息大小。
现在是棘手的部分我想建立一个宏,从类型创建位图。原因是我不希望位图和参数定义之间存在冗余。
我的问题是我试图编译的所有东西都失败了。
最后,我想要一个宏,例如:
#define GET_ENUM_FROM_TYPE(_type)

这就给了我根据类型的PARAMSIX SIUTIN 8,PARAMSIZE SIUTIN 16或PARAMSIZE UIT32 32。
限制:我在windows(armcl.exe)和C99上使用arm编译器。我不能用C11Generic()
我尝试了以下方法:
#define GET_ENUM_FROM_TYPE(_type)       \
(_type == uint8) ? PARAM_SIZE_UINT8 : \
        ((_type == uint16) ? PARAM_SIZE_UINT16 : \
                ((_type == uint32) ? PARAM_SIZE_UINT32 : PARAM_NONE))

最后我想用它来形容:
 #define LOGGER_MSG_ID_2_BITMAP              \
    (GET_ENUM_FROM_TYPE(ID_2_P3_TYPE) << 6 | \
     GET_ENUM_FROM_TYPE(ID_2_P2_TYPE) << 4 | \
     GET_ENUM_FROM_TYPE(ID_2_P1_TYPE) << 2 | \
     GET_ENUM_FROM_TYPE(ID_2_P0_TYPE))

但当我使用它时,它不会编译。
我有一张位图表:
uint8 paramsSizeBitmap [] = {
    LOGGER_MSG_ID_1_BITMAP,                         /*  LOGGER_MSG_ID_1   */
    LOGGER_MSG_ID_2_BITMAP,                         /*  LOGGER_MSG_ID_2   */
    LOGGER_MSG_ID_3_BITMAP,                         /*  LOGGER_MSG_ID_3   */
    LOGGER_MSG_ID_4_BITMAP,                         /*  LOGGER_MSG_ID_4   */
    LOGGER_MSG_ID_5_BITMAP,                         /*  LOGGER_MSG_ID_5   */
    LOGGER_MSG_ID_6_BITMAP,                         /*  LOGGER_MSG_ID_6   */
    LOGGER_MSG_ID_7_BITMAP,                         /*  LOGGER_MSG_ID_7   */
    LOGGER_MSG_ID_8_BITMAP,                         /*  LOGGER_MSG_ID_8   */
    LOGGER_MSG_ID_9_BITMAP,                         /*  LOGGER_MSG_ID_9   */
    LOGGER_MSG_ID_10_BITMAP,                        /*  LOGGER_MSG_ID_10  */
};

我得到这个错误:
line 39: error #18: expected a ")"
line 39: error #29: expected an expression

(第39行LOGGER_MSG_ID_2_BITMAP
我哪里做错了?
-----编辑-----
现在我有一个我不太喜欢的解决办法。
我不使用uint64,所以我使用了sizeof()宏,现在我的宏如下所示:
#define GET_ENUM_FROM_TYPE(_type)       \
(sizeof(_type) == sizeof(uint8)) ? PARAM_SIZE_UINT8 : \
        ((sizeof(_type) == sizeof(uint16)) ? PARAM_SIZE_UINT16 : \
                ((sizeof(_type) == sizeof(uint32)) ? PARAM_SIZE_UINT32 : PARAM_NONE))

我的助手名单是:
#define NO_PARAM                                    uint64

#define ID_2_P0_TYPE                                uint8
#define ID_2_P1_TYPE                                uint16
#define ID_2_P2_TYPE                                NO_PARAM
#define ID_2_P3_TYPE                                NO_PARAM

很好,但是。。。你知道的。。。

最佳答案

我认为解决方案是使用连接运算符##,并使用helper定义。

// These must match your enum
#define HELPER_0      PARAM_NONE
#define HELPER_uint8  PARAM_SIZE_UINT8
#define HELPER_uint16 PARAM_SIZE_UINT16
#define HELPER_uint32 PARAM_SIZE_UINT32

// Secondary macro to avoid expansion to HELPER__type
#define CONCAT(a, b) a ## b

// Outer parenthesis not strictly necessary here
#define GET_ENUM_FROM_TYPE(_type) (CONCAT(HELPER_, _type))

预处理后,GET_ENUM_FROM_TYPE(ID_2_P1_TYPE)将扩展到(PARAM_SIZE_UINT16)
注意,HELPER_***defines中的后缀必须与ID_*_P*_TYPE宏的内容完全匹配。例如HELPER_UINT8不起作用(无效情况)。(感谢@cxw)

关于c - 将枚举转换为c的宏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43978316/

10-13 06:20