编程时遇到一个需求,这是一个结构体,
struct srioMaintenanceData
{
unsigned int dstId;
unsigned int hopCnt;
unsigned int offset;
unsigned int value;
};
在代码中,想给这个结构体赋值,
maintData.dstId = 0xFF; maintData.hopCnt = 1;
maintData.offset = SRIO_REG_DEV_ID_CAR; maintData.value = 0;
想用一个宏来替代,类似于,
SRIO_MAINT_DATA_SET(maintData, 0xFF, 1, SRIO_REG_DEV_ID_CAR, 0);
我这样定义,
#define SRIO_MAINT_DATA_SET(n, a, b, c, d) n##.dstId=a;##n##.hopCnt=b;##n##.offset=c;##n##.value=d
Multiple markers at this line
- pasting "maintData" and "." does not give a valid preprocessing
token
- Invalid use of macro pasting in macro: SRIO_MAINT_DATA_SET
- in expansion of macro 'SRIO_MAINT_DATA_SET'
问题不知道怎么解决,搜了一下资料,据说vs中是不会报错的,根据C标准,用##操作后的结果必须是一个已经预定义过的符号。否则是未定义的。所以gcc和vs对于这个未定义行为表示了不同的看法,前者是给出错误,后者一笑而过。那什么是已经预定过的符号呢? 它包含了这些:头文件名, 等式, 预处理数字, 字符常数, 字符串值, 标点符号, 单个非空字符。
采取一种曲线救国策略,
inline void SRIO_MAINT_DATA_SET(struct srioMaintenanceData* p, unsigned int dstId, unsigned int hopCnt, unsigned int offset, unsigned int value)
{
p->dstId = dstId;
p->hopCnt = hopCnt;
p->offset = offset;
p->value = value;
}
希望有大神可以在评论区告知怎样用宏完成结构体赋值,可能在linux内核代码里有类似操作。
2018-06-19补充:今天写windows驱动看到WDK的一个实现:
WDF_DMA_ENABLER_CONFIG dmaConfig;
WDF_DMA_ENABLER_CONFIG_INIT( &dmaConfig,
WdfDmaProfileScatterGather64Duplex,
DevExt->MaximumTransferLength );
WDK是这样实现的,也使用的inline。表示心里略平衡一点。
VOID
FORCEINLINE
WDF_DMA_ENABLER_CONFIG_INIT(
__out PWDF_DMA_ENABLER_CONFIG Config,
__in WDF_DMA_PROFILE Profile,
__in size_t MaximumLength
)
{
RtlZeroMemory(Config, sizeof(WDF_DMA_ENABLER_CONFIG));
Config->Size = sizeof(WDF_DMA_ENABLER_CONFIG);
Config->Profile = Profile;
Config->MaximumLength = MaximumLength;
}
宏定义中的#,##
关于宏##的使用注意一点