我试了一个多星期都没有成功。
我正在创建两个处理器之间的日志接口,我需要有关定义自动宏的帮助。
我什么意思?
假设我有一个定义为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编译器。我不能用C11
Generic()
。我尝试了以下方法:
#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/