У меня есть следующий фрагмент кода на C, который работает безупречно. Я определяю NAME_LIST
, чтобы облегчить создание NAMES_TABLE
.
#include <stdio.h>
#include <stdint.h>
typedef enum {
NAME_1 = 0,
NAME_2 = 1,
NAME_3 = 2,
NAME_4 = 3,
} name_t;
typedef struct {
const uint8_t num_names;
const name_t *name_list;
} name_struct_t;
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define NAME_LIST(...) { \
.num_names = ARRAY_SIZE(((name_t[]){__VA_ARGS__})), \
.name_list = (name_t[]){__VA_ARGS__} \
}
name_struct_t NAMES_TABLE[] = {
NAME_LIST(NAME_1),
NAME_LIST(NAME_2, NAME_3),
NAME_LIST(NAME_4),
};
Я хочу расширить предыдущий код и добавить фиксированный входной аргумент в NAME_LIST
МАКРОС, чтобы указать конкретное состояние, которое будет обрабатываться позже в коде.
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
typedef enum {
NAME_1 = 0,
NAME_2 = 1,
NAME_3 = 2,
NAME_4 = 3,
} name_t;
typedef struct {
const uint8_t num_names;
const name_t *name_list;
const bool flag;
} name_struct_t;
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define NAME_LIST(flag, ...) { \
.num_names = ARRAY_SIZE(((name_t[]){__VA_ARGS__})), \
.name_list = (name_t[]){__VA_ARGS__} \
.flag = (bool)(flag) \
}
name_struct_t NAMES_TABLE[] = {
NAME_LIST(true, NAME_1),
NAME_LIST(false, NAME_2, NAME_3),
NAME_LIST(true, NAME_4),
};
Однако я получаю следующие ошибки, которые не могу устранить.
main.c:36:19: error: expected identifier before numeric constant
36 | NAME_LIST(true, NAME_1),
| ^~~~
main.c:32:10: note: in definition of macro ‘NAME_LIST’
32 | .flag = (bool)(flag) \
| ^~~~
main.c:37:19: error: expected identifier before numeric constant
37 | NAME_LIST(false, NAME_2, NAME_3),
| ^~~~~
main.c:32:10: note: in definition of macro ‘NAME_LIST’
32 | .flag = (bool)(flag) \
| ^~~~
main.c:38:19: error: expected identifier before numeric constant
38 | NAME_LIST(true, NAME_4),
| ^~~~
main.c:32:10: note: in definition of macro ‘NAME_LIST’
32 | .flag = (bool)(flag) \
| ^~~~
Есть идеи, правильно ли расширение определения MARCO, которое я сделал, или есть альтернативный способ сделать это?
flag
расширяется как значение поля (которое вам нужно), так и имя поля (которое вам не нужно), поэтому переименуйте аргумент. Также в строке перед ней отсутствует запятая. Так:
#define NAME_LIST(flagv, ...) { \
.num_names = ARRAY_SIZE(((name_t[]){__VA_ARGS__})), \
.name_list = (name_t[]){__VA_ARGS__}, \
.flag = (bool)(flagv) \
}
Ему не нравится, что вы используете flag
для параметра макроса и члена struct
одновременно. Переименовав один из них в другое и добавив недостающую запятую после .name_list = (name_t[]){__VA_ARGS__}
, все заработает:
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
typedef enum {
NAME_1 = 0,
NAME_2 = 1,
NAME_3 = 2,
NAME_4 = 3,
} name_t;
typedef struct {
const uint8_t num_names;
const name_t *name_list;
const bool flag;
} name_struct_t;
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define NAME_LIST(xyz, ...) { \
.num_names = ARRAY_SIZE(((name_t[]){__VA_ARGS__})), \
.name_list = (name_t[]){__VA_ARGS__}, \
.flag = (bool)(xyz) \
}
name_struct_t NAMES_TABLE[] = {
NAME_LIST(true, NAME_1),
NAME_LIST(false, NAME_2, NAME_3),
NAME_LIST(true, NAME_4),
};
.flag = (bool)(flag)
расширяется до.true = (bool)(true)
.