对于在预处理器阶段展开的循环宏?

时间:2013-10-01 13:17:02

标签: c gcc linux-kernel c-preprocessor

我想使用gcc预处理器编写几乎相同的代码声明500次。让我们说出于演示目的,我想使用宏FOR_MACRO

#define FOR_MACRO(x) \
    #for i in {1 ... x}: \
        const int arr_len_##x[i] = {i};

并且调用FOR_MACRO(100)将转换为:

const int arr_len_1[1] = {1};
const int arr_len_2[2] = {2};

...

const int arr_len_100[100] = {100};

4 个答案:

答案 0 :(得分:10)

这不是一个好主意:

虽然原则上可行,但使用预处理器意味着您必须至少手动展开循环一次,最终会在循环深度上产生一些任意实现定义的限制,并且所有语句都将在一行中生成。

更好地使用您选择的脚本语言来生成代码(可能在单独的可包含文件中)并将其与您的构建过程集成。

答案 1 :(得分:3)

如果您迫切需要,可以使用Order-PP

它是预处理器中实现的脚本语言。这意味着它在概念上类似于使用脚本语言生成C代码(事实上,相同),除了没有外部工具,并且脚本与C编译器同时运行:一切都是用C宏完成的。尽管是在预处理器上构建的,但循环迭代,递归深度或类似的东西没有真正的限制(限制在数十亿的某个地方,你不必担心它)。

要发出问题示例中请求的代码,您可以写:

#include <order/interpreter.h>

ORDER_PP(    // runs Order code
  8for_each_in_range(8fn(8I,
                         8print( 8cat(8(const int arr_len_), 8I)
                                   ([) 8I (] = {) 8I (};) )),
                     1, 101)
)

我无法理解为什么要这样做,而不是简单地将像Python这样的外部语言集成到您的构建过程中(订单可能是使用宏实现,但它仍然是一个单独的语言来理解),但选项就在那里。

据我所知,订单仅适用于海湾合作委员会;其他预处理器过快地耗尽堆栈(甚至是Clang),或者不完全符合标准。

答案 2 :(得分:1)

您确定不能以更好的方式处理问题,而不是为您提供完全解决问题的解决方案吗?

也许

会更好
  • 使用一个多维度的数组
  • 在运行时使用数组填充数据,因为您显然希望填写每个数组的第一个条目。如果你保持数组未初始化,它将(在模块级别定义)将被放入.bss段而不是.data,并且二进制文件中可能需要更少的空间。

答案 3 :(得分:1)

您可以使用例如P99来执行此类预处理器代码展开。但由于预处理器的容量有限,因此有限制,并且该限制通常低于500