【问题标题】:C macro expansion orderC 宏扩展命令
【发布时间】:2016-07-15 12:55:10
【问题描述】:

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

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。那么,有没有办法将这些值扩展为最终的数值,然后再将其连接到其他宏?

【问题讨论】:

  • 为什么不简单地使用循环或memset()?是的,它们在运行时工作,但相对容易达到预期的效果。
  • GCC 有一个扩展,允许您将一系列元素初始化为相同的值,例如 int array[ARRAY_LENGTH] = { [0 ... 3] = -2, [4] = 10, [5] = 2, [6 ... ARRAY_LENGTH - 1] = -2, };
  • @Peter 我知道,但我在嵌入式系统中工作,我想将它存储在闪存中(使用 const 限定符更新问题)
  • @IanAbbott 我不知道那个,即使它不是 ANSI C 我也不介意,GCC 对我来说很好。你能回复那个,这样我就可以把它作为正确的答案?
  • 你能用boost preprocessor吗?如果是,那么,例如,BOOST_PP_REPEAT 看起来很有趣。

标签: c macros c-preprocessor


【解决方案1】:

您可以通过将MACRO_REPEAT 的定义更改为使用2 阶段扩展来解决MACRO_REPEAT(ARRAY_LENGTH , -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 扩展,请直接使用它们。

【讨论】:

  • 我知道,但是具有 X 列和 Y 行的多维数组只是查看 X*Y 单维数组的另一种方式。我相信你可以做 int array[1][2] = {first, second} 之类的东西, first 将存储在 [0][0] 中,另一个存储在 [0][1]
  • @munes:你是对的:如果你可以将宏扩展为 262144 个初始化器的序列,它将起作用。使用您当前的宏定义尝试 MACRO_REPEAT(512, { MACRO_REPEAT(512, -2) })
  • @munes:我并不感到惊讶,无论是实际宏定义的问题还是宏扩展的限制。
【解决方案2】:

我不确定这是否算作“正确”答案,因为它不能直接回答 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,
    /* ... */
};

【讨论】:

  • 您知道吗,您说得对,这不是原始问题的答案(因此应该扩大范围)。很抱歉重新发布请求,chqrlie 回答它更接近正确答案
猜你喜欢
  • 2021-07-17
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 2014-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多