为什么此宏不能正确扩展?

Abh*_*gar 4 c

我试图初始化数组,如下所示:

   static tha_field_info_t person_t_fields[] = {
            HA_FIELD_INFO(person_t, name, CHAR)
    };
Run Code Online (Sandbox Code Playgroud)

相关数据结构:

typedef struct _tha_field_info_{
    char fname[128];
    DATA_TYPE_t dtype;
    unsigned int size;
    unsigned int offset;
} tha_field_info_t;

typedef struct _person{
    char name[30];
    unsigned int age;
} person_t;
Run Code Online (Sandbox Code Playgroud)

使用的宏

#define HA_FIELD_OFFSET(st, name)       ((int)&((st *)0)->name)
#define HA_FIELD_SIZE(st, name)         sizeof (((st *)0)->name)

#define HA_FIELD_INFO (st, fname, dtype)   \
{#fname, dtype, HA_FIELD_SIZE(st, fname), HA_FIELD_OFFSET(st, fname)}
Run Code Online (Sandbox Code Playgroud)

使用此宏看到编译错误。

tha.h:35:28: error: ‘fname’ undeclared (first use in this function)
tha.h:35:35: error: ‘dtype’ undeclared (first use in this function)
tha.h:36:2: error: expected ‘}’ before ‘{’ token
{#fname, dtype, HA_FIELD_SIZE(st, fname), HA_FIELD_OFFSET(st, fname)}
tha.h:36:3: error: stray ‘#’ in program
{#fname, dtype, HA_FIELD_SIZE(st, fname), HA_FIELD_OFFSET(st, fname)}
Run Code Online (Sandbox Code Playgroud)

但是,如果我像这样进行硬编码,则其工作正常。

{"name", CHAR, sizeof(((person_t *)0)->name), ((int)&((person_t *)0)->name)}

基本上,我想用结构person_t的字段信息存储数组。

小智 5

C中有两种类型的定义指令:

#define OBJECT_LIKE_MACRO     followed by a "replacement list" of preprocessor tokens
#define FUNCTION_LIKE_MACRO(with, arguments) followed by a replacement list
Run Code Online (Sandbox Code Playgroud)

区分这两种类型的宏的是标记后的标识符#define:如果是lparen,则为类似函数的宏,否则为类似对象的宏。什么是lparen?N1570草案在附录A第3节中指出:

(6.10)LPAREN:
  一个(字符不能立即通过空白前面

据我所知,这是C中少数几个重要的间隔之一(除了//注释,行拼接和预处理指令)。而且这很有道理。毕竟,预处理器如何区分任何函数式宏和具有以(令牌开头的替换列表的对象式宏?例如,以下是类似于对象的宏,而不是语法错误的类似于函数的宏:

#define NULL (void*)0
Run Code Online (Sandbox Code Playgroud)

现在让我们回答您的问题。问题出在这两行:

#define HA_FIELD_INFO (st, fname, dtype)   \
{#fname, dtype, HA_FIELD_SIZE(st, fname), HA_FIELD_OFFSET(st, fname)}
Run Code Online (Sandbox Code Playgroud)

因为(after字符HA_FIELD_INFO是“以空格开头”,所以这不是您想要的类似函数的宏。只需删除该空间:

#define HA_FIELD_INFO(st, fname, dtype)   \
{#fname, dtype, HA_FIELD_SIZE(st, fname), HA_FIELD_OFFSET(st, fname)}
Run Code Online (Sandbox Code Playgroud)