I have a macro to repeat macros that I use to fill arrays with default values in compile time:
const int array [512] =
{
MACRO_REPEAT(512, -2) // this repeats -2, 512 times
[4] = 10,
[5] = 2,
...
}
The macro repeat will expand to MACRO_REPEAT_512, but now I wanted to use other macros as the array size, like:
#define ARRAY_LENGTH 512
const int array [ARRAY_LENGTH ] =
{
MACRO_REPEAT(ARRAY_LENGTH , -2) // this repeats -2, 512 times
[4] = 10,
[5] = 2,
...
}
But this expands to MACRO_REPEAT_ARRAY_LENGTH, doesn't expand ARRAY_LENGTH
value before concatenating it. Other example would be for multi-dimensional arrays, which involves more levels of expansion:
#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,
...
}
This will expand to MARO_REPEAT_X*Y. So, is there a way to expand those values to the final numerical value before concatenating it to other macros?
You can solve the MACRO_REPEAT(ARRAY_LENGTH , -2)
case by changing the definition of MACRO_REPEAT
to use 2 stage expansion, ie do not use token pasting in MACRO_REPEAT
itself, invoke another macro that does.
Not that this will only work as expected if ARRAY_LENGTH
is defined as a single number token and if there is a macro definition for this specific size.
You cannot handle the more general MACRO_REPEAT(X*Y , -2)
case with the standard C preprocessor.
You can use the gcc extension to initialize simple arrays:
#define MACRO_REPEAT(n, e) [ 0 ... (n)-1 ] = (e),
But this method cannot be used to handle multidimensional arrays such as MACRO_REPEAT(X*Y , -2)
.
You could try this:
#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) }) };
But the use of the C preprocessor just obfuscates the intent. If you decide to rely on gcc extensions, just use them directly.
I'm not sure if this counts as the "right" answer as it doesn't answer the OP's question directly, but it is a suggested workaround for the problem. It also is not standard C as it makes use of a GCC extension.
In the GNU C Compiler (gcc), a range of array elements can be initialized to the same value using the form [FIRST ... LAST] = VALUE
. It also appears to allow more than one designated initializer for an element, so it is possible to initialize a range of elements to the same value and then initialize elements contained within that range to different values, something like this:
#define ARRAY_LENGTH 512
const int array[ARRAY_LENGTH] =
{
[0 ... ARRAY_LENGTH - 1] = -2,
[4] = 10,
[5] = 2,
/* ... */
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With