MSVC:将结构映射到offsetof数组时出错

时间:2017-09-02 13:47:16

标签: c c-preprocessor

我正在尝试使用结构字段的偏移填充数组,我正在尝试执行以下操作

#define EXPAND_(X) X
#define TYPE_ARG_N(_0, _1, _2, N, ...) N
#define TYPE_OFFSET_1(S, _0) { sizeof(S), { offsetof(S, _0) } }
#define TYPE_OFFSET_2(S, _0, _1) { sizeof(S), { offsetof(S, _0), offsetof(S, _1) } }
#define TYPE_OFFSET_3(S, _0, _1, _2) { sizeof(S), { offsetof(S, _0), offsetof(S, _1), offsetof(S, _2) } }
#define TYPE_OFFSET_LIST() TYPE_OFFSET_3, TYPE_OFFSET_2, TYPE_OFFSET_1
#define TYPE_OFFSET_N_(...) EXPAND_(TYPE_ARG_N(__VA_ARGS__))
#define TYPE_OFFSET_ARGS(...) EXPAND_(__VA_ARGS__)
#define TYPE_OFFSET_SELECT(...) TYPE_OFFSET_N_(__VA_ARGS__, TYPE_OFFSET_LIST())
#define TYPE_OFFSET(S, ...) TYPE_OFFSET_SELECT(__VA_ARGS__)(S, TYPE_OFFSET_ARGS(__VA_ARGS__))

typedef struct {
    size_t      size;
    size_t*     offsets;
} tTable;

tTable t = TYPE_OFFSET(tTable, size, offsets);

MSVC2017失败并出现以下情况:

error C4003: not enough actual parameters for macro 'TYPE_OFFSET_2'
error C2065: 'offsets': undeclared identifier
error C2102: '&' requires l-value

有关如何修复这些宏的想法吗?

1 个答案:

答案 0 :(得分:0)

对于这样的调试,请尝试使用/EP标志通过 预处理器运行。使用您的代码执行此操作会显示以下输出:

typedef struct {
    size_t      size;
    size_t*     offsets;
} tTable;

tTable t = fxma.h(17) : warning C4003: not enough actual parameters for macro 'TYPE_OFFSET_2'
{ sizeof(tTable), { offsetof(tTable, size, offsets), offsetof(tTable, ) } };

这里的问题是,微软的预处理器有一个单一宏参数的概念,其中包含逗号。当通过扩展另一个宏产生逗号时会发生这种情况。

特别是,TYPE_OFFSETTYPE_OFFSET_2 (tTable, size, offset)一起调用size, offset(是TYPE_OFFSET_ARGS(__VA_ARGS__)的扩展)isn&实际上有两个不同的论点......它只有1. TYPE_OFFSET_2然后才得到两个论点;换句话说:

  • StTable1
  • _0size, offset
  • _1缺失

(你可以在扩展中看到这一点; offsetof(tTable, size, offsets))。

修复是添加间接级别。将此版本的TYPE_OFFSET替换为:

#define TYPE_OFFSET_CALL(X, Y) X Y
#define TYPE_OFFSET(S, ...) TYPE_OFFSET_CALL(TYPE_OFFSET_SELECT(__VA_ARGS__),(S, TYPE_OFFSET_ARGS(__VA_ARGS__)))