Формат массива для #define (препроцессор C)
Вероятно, наивный вопрос - я использовал программу 20 лет назад и не кодировал много с тех пор. Моя память о том, как работает C preprocessor
, сильно атрофировалась с тех пор...
Я пишу очень простую программу C
, и я пытаюсь объявить несколько статических глобальных массивов, но размер arrays
будет зависеть (на нетривиальном пути) от переменной MODE
, Что-то вроде упрощенного примера ниже.
Два быстрых пункта: я знаю, что могу просто размер arrays
в соответствии с наибольшим размером, необходимым для любого MODE
, но я не хочу этого, потому что (в отличие от упрощенного примера ниже) иногда несколько эти размеры будут чрезвычайно большими, а другие - крошечными.
Кроме того, я хочу использовать статически определенные глобальные массивы, а не динамически выделять их во время выполнения. Я хочу, чтобы компилятор имел размеры во время компиляции.
//** Simplified example of what I'd like to do **//
#define SIZE_LIST_1[5] = {2, 7, 23, 33, 12, 76} // I don't think this is valid syntax
#define SIZE_LIST_2[5] = {11, 65, 222, 112, 444}
#define MODE 4
#define S1 SIZE_LIST_1[MODE]
#define S2 SIZE_LIST_2[MODE]
int a[S1], b[S2];
Ответы
Ответ 1
Прежде чем вы сможете сделать это, вам нужно определить кучу вспомогательных макросов:
#define CONCAT(A,B) A ## B
#define EXPAND_CONCAT(A,B) CONCAT(A, B)
#define ARGN(N, LIST) EXPAND_CONCAT(ARG_, N) LIST
#define ARG_0(A0, ...) A0
#define ARG_1(A0, A1, ...) A1
#define ARG_2(A0, A1, A2, ...) A2
#define ARG_3(A0, A1, A2, A3, ...) A3
#define ARG_4(A0, A1, A2, A3, A4, ...) A4
#define ARG_5(A0, A1, A2, A3, A4, A5, ...) A5
#define ARG_6(A0, A1, A2, A3, A4, A5, A6, ...) A6
#define ARG_7(A0, A1, A2, A3, A4, A5, A6, A7, ...) A7
#define ARG_8(A0, A1, A2, A3, A4, A5, A6, A7, A8, ...) A8
#define ARG_9(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, ...) A9
#define ARG_10(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, ...) A10
/* above should be in a pp_helper.h header file or some such */
#define SIZE_LIST_1 ( 2, 7, 23, 33, 12, 76)
#define SIZE_LIST_2 (11, 65, 222, 112, 444, 1000)
#define S1 ARGN(MODE, SIZE_LIST_1)
#define S2 ARGN(MODE, SIZE_LIST_2)
#define MODE 4
int a[S1], b[S2];
Есть куча препроцессорных "библиотек", которые вы можете получить с кодом шаблона (boost PP, P99), или вы можете просто свернуть свой собственный. Основная проблема заключается в том, что вам нужно определить макросы ARG на основе наибольшего количества аргументов, которые вы когда-либо захотите обработать.
Ответ 2
Возможно, лучшее, что вы можете сделать, это что-то вроде этого:
#define SIZE_LIST_1_0 2
#define SIZE_LIST_1_1 7
#define SIZE_LIST_1_2 23
#define SIZE_LIST_1_3 33
#define SIZE_LIST_1_4 12
#define SIZE_LIST_2_0 11
#define SIZE_LIST_2_1 65
#define SIZE_LIST_2_2 222
#define SIZE_LIST_2_3 112
#define SIZE_LIST_2_4 444
#define MODE 4
#define S1 SIZE_LIST_1_##MODE
#define S2 SIZE_LIST_2_##MODE
int a[S1], b[S2];
Ответ 3
Я боюсь, что такой возможности нет.
Вместо этого предлагаю следующий подход:
#define MODE 0
#define DECLARE_ARRAYS_WITH_SIZES(S1, S2, S3) \
int arr1[S1]; \
int arr2[S2]; \
int arr3[S3];
#if MODE == 0
DECLARE_ARRAYS_WITH_SIZES(3, 6, 7)
#elif MODE == 1
DECLARE_ARRAYS_WITH_SIZES(8, 2, 1)
#endif