我正在尝试按如下方式初始化数组:
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的字段信息的数组。
答案 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)}