C宏展开顺序

mrzz3bfm  于 2023-10-16  发布在  其他
关注(0)|答案(2)|浏览(87)

我有一个宏来重复我用来在编译时用默认值填充数组的宏:

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

宏repeat将扩展到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。那么,有没有一种方法可以在将这些值连接到其他宏之前将其扩展为最终的数值?

67up9zun

67up9zun1#

你可以通过改变MACRO_REPEAT的定义来解决MACRO_REPEAT(ARRAY_LENGTH , -2)的情况,使用2阶段扩展,即不要在MACRO_REPEAT本身中使用标记粘贴,调用另一个宏。
这并不是说只有当ARRAY_LENGTH被定义为单个数字标记并且有一个针对此特定大小的宏定义时才能按预期工作。
使用标准C预处理器无法处理更一般的MACRO_REPEAT(X*Y , -2)情况。
你可以使用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扩展,直接使用它们就行了。

w6mmgewl

w6mmgewl2#

我不确定这是否算是“正确”的答案,因为它没有直接回答OP的问题,但它是一个建议的解决问题的方法。它也不是标准C,因为它使用了GCC扩展。
在GNU C语言(gcc)中,数组元素的范围可以使用[FIRST ... LAST] = VALUE形式初始化为相同的值。它似乎还允许一个元素有多个指定的初始化器,因此可以将一个范围内的元素初始化为相同的值,然后将该范围内包含的元素初始化为不同的值,类似于:

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

额外奖励内容2023-10-07

可以定义一个helper macro:

#define ARANGE(n) [0 ... (n) - 1]

并在初始化器中使用如下:

#define ARANGE(n) [0 ... (n) - 1]

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

对于2-D阵列情况:

#define ARANGE(n) [0 ... (n) - 1]

#define X 512
#define Y 512
const int array[X][Y] =
{
    ARANGE(X) =
    {
        ARANGE(Y) = -2,
        [4] = 10,
        [5] = 2,
        /* ... */
    },
    [4] =
    {
        ARANGE(Y) = -3,
        [42] = 23,
        /* ... */
    },
    /* ... */   
};

相关问题