C语言宏##高级用法-给结构体赋值问题

问题

编程时遇到一个需求,这是一个结构体,

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

报错,但这不是语法错误,是编译器不支持这个操作。
C语言宏##高级用法-给结构体赋值问题_第1张图片

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;
}

参考

宏定义中的#,##
关于宏##的使用注意一点

你可能感兴趣的:(linux应用开发)