C целью расширения макроса

у меня есть макрос для повторения макросов, которые я использую для заполнения массивов значениями по умолчанию во время компиляции:

const int array [512] = 
{
     MACRO_REPEAT(512, -2) // this repeats -2, 512  times
     [4] = 10,
     [5] = 2,
     ...
}

повторение макроса расширится до MACRO_REPEAT_512, но теперь я хотел использовать другие макросы в качестве размера массива, например:

#define ARRAY_LENGTH 512
const int array [ARRAY_LENGTH ] = 
{
    MACRO_REPEAT(ARRAY_LENGTH , -2) // this repeats -2, 512  times
    [4] = 10,
    [5] = 2,
     ...
 }

но это расширяется до MACRO_REPEAT_ARRAY_LENGTH, не расширяется ARRAY_LENGTH значение перед объединением. Другим примером может быть многомерные массивы, которые включают в себя больше уровней расширение:

#define X 512
#define Y 512

const int array [X][Y] = 
{
    MACRO_REPEAT(X*Y , -2) // this repeats -2, 512  times
    [4] = 10,
    [5] = 2,
     ...
 }

это расширится до MARO_REPEAT_X * Y. Итак, есть ли способ расширить эти значения до конечного числового значения, прежде чем объединять его с другими макросами?

2 ответов


вы можете решить MACRO_REPEAT(ARRAY_LENGTH , -2) case путем изменения определения MACRO_REPEAT для использования расширения 2 этапа, т. е. не используйте вставку токенов в MACRO_REPEAT сам, вызовите другой макрос, который делает.

не то, что это будет работать только так, как ожидалось, если ARRAY_LENGTH определяется как маркер одного числа и если есть определение макроса для этого определенного размера.

вы не можете справиться с более общей MACRO_REPEAT(X*Y , -2) случай со стандартным препроцессором C.

вы можете использовать расширение gcc для инициализации простых массивов:

#define MACRO_REPEAT(n, e)  [ 0 ... (n)-1 ] = (e),

но этот метод нельзя использовать для обработки многомерных массивов, таких как MACRO_REPEAT(X*Y , -2).

вы можете попробовать это:

#define MACRO_REPEAT(n, e)  [ 0 ... (n)-1 ] = (e),
#define X 512
#define Y 512

const int array[X][Y] = { MACRO_REPEAT(X, { MACRO_REPEAT(Y, -2) }) };

но использование препроцессора C просто запутывает намерение. Если вы решили полагаться на расширения gcc, просто используйте их напрямую.


Я не уверен, что это считается "правильным" ответом, поскольку он не отвечает на вопрос OP напрямую, но это предлагаемое обходное решение проблемы. Он также не является стандартным C, поскольку он использует расширение GCC.

в компиляторе GNU C (gcc) диапазон элементов массива может быть инициализирован с тем же значением, используя форму [FIRST ... LAST] = VALUE. Он также позволяет использовать более одного назначенного инициализатора для элемента, поэтому можно инициализировать диапазон элементов одинаково value, а затем инициализировать элементы, содержащиеся в этом диапазоне, для разных значений, что-то вроде этого:

#define ARRAY_LENGTH 512
const int array[ARRAY_LENGTH] =
{
    [0 ... ARRAY_LENGTH - 1] = -2,
    [4] = 10,
    [5] = 2,
    /* ... */
};