为什么这个宏没有正确扩展?

时间:2016-10-08 11:16:41

标签: c

我正在尝试按如下方式初始化数组:

   static tha_field_info_t person_t_fields[] = {
            HA_FIELD_INFO(person_t, name, CHAR)
    };

相关数据结构:

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;

使用的宏

#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)}

使用此宏查看编译错误。

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

但是,如果我像这样硬编码,那么它的工作正常。

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

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

1 个答案:

答案 0 :(得分:4)

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

#define OBJECT_LIKE_MACRO     followed by a "replacement list" of preprocessor tokens
#define FUNCTION_LIKE_MACRO(with, arguments) followed by a replacement list

这两种类型的宏的区别在于#define之后的标识符后面的标记:如果它是 lparen ,它是一个类似函数的宏,否则它是一个对象 - 像宏。什么是 lparen Draft N1570在附录A第3节中指出:

  

(6.10)lparen:
   ( 字符不会立即以空格

开头

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

#define NULL (void*)0

现在让我们回答你的问题。问题出在以下两行:

#define HA_FIELD_INFO (st, fname, dtype)   \
{#fname, dtype, HA_FIELD_SIZE(st, fname), HA_FIELD_OFFSET(st, fname)}

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

#define HA_FIELD_INFO(st, fname, dtype)   \
{#fname, dtype, HA_FIELD_SIZE(st, fname), HA_FIELD_OFFSET(st, fname)}