宏可以接受类型吗?

时间:2015-01-28 07:18:38

标签: objective-c c c-preprocessor

除非我的理解不正确,否则以下宏

int i; // for loop
const char* ctype; // proprietary type string
void** pool = malloc(sizeof(void*) * (nexpected - 1));
size_t poolc = 0;

#define SET(type, fn) type* v = (pool[poolc++] = malloc(sizeof(type)));         \
    *v = (type) fn(L, i)
#define CHECK(chr, type, fn) case chr:                                          \
    SET(type, fn);                                                              \
    break

switch (ctype[0]) {
  CHECK('c', char, lua_tonumber);
}

应扩展为

int i; // for loop
const char* ctype; // proprietary type string
void** pool = malloc(sizeof(void*) * (nexpected - 1));
size_t poolc = 0;

switch (ctype[0]) {
  case 'c':
    char* v = (pool[poolc++] = malloc(sizeof(char)));
    *v = (char) lua_tonumber(L, i);
    break;
}

但在编译时,我得到:

src/lua/snip.m:185:16: error: expected expression
    CHECK('c', char, lua_tonumber);
               ^
src/lua/snip.m:181:9: note: expanded from macro 'CHECK'
    SET(type, fn);                                                              \
        ^
src/lua/snip.m:178:23: note: expanded from macro 'SET'
#define SET(type, fn) type* v = (pool[poolc++] = malloc(sizeof(type)));         \
                      ^
src/lua/snip.m:185:5: error: use of undeclared identifier 'v'
    CHECK('c', char, lua_tonumber);
    ^
src/lua/snip.m:181:5: note: expanded from macro 'CHECK'
    SET(type, fn);                                                              \
    ^
src/lua/snip.m:179:6: note: expanded from macro 'SET'
    *v = (type) fn(L, i)
     ^
2 errors generated.

这里发生了什么?预处理器不是文字替换引擎吗?为什么要尝试评估表达式?

请记住,这看起来像直C,这实际上是C11标准下的目标C(注意.m)。不确定这是否有所不同。

如果不扩展每个条目的代码,我将失去如何继续。

1 个答案:

答案 0 :(得分:5)

您的理解是正确的!但是你遇到了C语言的怪癖。 A label, including a case label, must be followed by an expression, not a variable declaration.

您可以通过在0;之后插入空语句(例如case)或将case主体括在一组大括号中来解决此问题。这样做的一种实用方法可能是将CHECK重新定义为:

#define CHECK(chr, type, fn) \
    case chr: { SET(type,fn); } break;