如何评估预处理器宏中的参数以传递给sizeof?

时间:2017-07-17 15:45:11

标签: c++ c c-preprocessor

我想要一个打印出结构成员变量信息的函数。为了使函数尽可能简单(并且没有错误),我也不想手动传入类型。这使我需要能够评估传递给我的宏的参数:

#ifndef preprocessor_stringify
#define preprocessor_stringify(s) #s
#endif

typedef struct test_s {
    void (*ptr)(void*);
} test;

void doSomething_(char *name, int offset, int size){
    printf("%s %d %d\n", name, offset, size);
}

#define doSomething(name, container) (\
    doSomething_(\
        preprocessor_stringify(name),\
        offsetof(container, name),\
        sizeof(container->name))\
    );

int main(){
    doSomething(ptr, test);
    return 0;
}

这会产生编译错误 test.cpp:21:19: error: expected primary-expression before ‘->’ token sizeof(container->name))\

有关如何解决此问题的任何想法?我希望解决方案兼容c和c ++。

2 个答案:

答案 0 :(得分:6)

#include <stdio.h>
#include <stddef.h>

#ifndef preprocessor_stringify
#define preprocessor_stringify(s) #s
#endif

typedef struct test_s {
    void (*ptr)(void*);
} test;

void doSomething_(char const *name, int offset, int size){
    printf("%s %d %d\n", name, offset, size);
}

#define doSomething(name, container) (\
    doSomething_(\
        preprocessor_stringify(name),\
        offsetof(container, name),\
        sizeof(((container*)0)->name))\
    );

int main(){
    doSomething(ptr, test);
    return 0;
}

我做了两处修改:

  1. 在c ++中,字符串文字为const char[]
  2. void doSomething_(char const *name, int offset, int size){
    
    1. 我们想要一个模型对象的sizeof,所以我们必须创建一个模型:
    2. sizeof(((container*)0)->name))\
      

      其中一条评论提到指针转换是丑陋的。我同意,让我们把它限制在一个我们可以重复使用的宏。

      #define sizeof_member(Class, Member) sizeof ((Class*)0)->Member
      
      #define doSomething(name, container) (\
          doSomething_(\
              preprocessor_stringify(name),\
              offsetof(container, name),\
              sizeof_member(container, name)) \
          );
      

答案 1 :(得分:-1)

另一种选择是使用临时对象。

#define doSomething(name, container)      \
    do {                                  \
        container temp;                   \
        doSomething_(                     \
            preprocessor_stringify(name), \
            offsetof(container, name),    \
            sizeof(temp.name)             \
        );                                \
    } while(0)

很可能该对象被优化掉了。 (可能不适用于复杂的C ++对象)。