C语言 如何使预处理器宏在编译前评估代码



我使用宏在我的代码中定义一些数组的静态大小,我在代码的顶部定义了一个配置宏变量,一些宏变量依赖于所述宏变量。我可以创建一个函数,该函数接受该值并返回所需的数组大小,但这将在运行时执行,我需要使用vla。下面的示例显示了一个数字(没有重复数字)的SIZE宏,以及该数字是否可以以零("0123"对"1234")。

在运行时计算LIMIT的代码:
int limit(int size, int npz){
l = npz ? 9 : 10;
for(int i = 1; i < size; i++)
l *= 10 - i;
return l;
}

i手动计算所有值的上述数字的数量。有解决办法吗?

#define SIZE 4 // 1 .. 10
#define NO_PADDING_ZERO 1 // 1 | 0
#if NO_PADDING_ZERO
#if SIZE == 1
#define LIMIT 9
#elif SIZE == 2
#define LIMIT 81
#elif SIZE == 3
#define LIMIT 648
#elif SIZE == 4
#define LIMIT 4536
#elif SIZE == 5
#define LIMIT 27216
#elif SIZE == 6
#define LIMIT 136080
#elif SIZE == 7
#define LIMIT 544320
#elif SIZE == 8
#define LIMIT 1632960
#else
#define LIMIT 3265920
#endif
#else
#if SIZE == 1
#define LIMIT 10
#elif SIZE == 2
#define LIMIT 90
#elif SIZE == 3
#define LIMIT 720
#elif SIZE == 4
#define LIMIT 5040
#elif SIZE == 5
#define LIMIT 30240
#elif SIZE == 6
#define LIMIT 151200
#elif SIZE == 7
#define LIMIT 604800
#elif SIZE == 8
#define LIMIT 1814400
#else
#define LIMIT 3628800
#endif
#endif

解决方法可以是从其他地方生成C代码。

考虑学习更多,使用GPP或您自己的C代码生成器(可能使用GNU bison,在某些简单的情况下使用GNU gawk或GNU autoconf)。

请注意,在Linux或POSIX上,您可以生成C代码,将其编译为插件,然后打开该插件。有关无用的示例,请参阅manydl.c。有关有用的(但过时的)示例,请参阅我的旧GCC MELT。

另一种方法(特定于GCC)可能是用GCC插件扩展编译器。看到bismon。

您还可以使用GNU lightning或(在c++中)asmjit生成机器代码(在您的程序中)。然后读龙的书和这个答案。

阅读Jacques Pitrat解释元编程方法(在RefPerSys中重用)的一些书

与部分求值相关的概念是相关的。

这是某种阶乘吗?

(10 - NO_PADDING_ZERO) * 9 * 8 * ... * (10 - LIMIT)

你可以在宏或内联函数的循环表达式中使用它,优化编译器将在编译时计算它。

#include <bool.h>
inline int limit(int size, bool npz){
int l = 10 - npz;
for(int i = 1; i < size; i++)
l *= 10 - i;
return l;
}
#define LIMIT (limit(SIZE, NO_PADDING_ZERO))

如果您愿意,您可以定义一个预先计算的数组并使用

#define LIMIT (array[SIZE][NO_PADDING_ZERO])

最新更新