c-如何让gcc预处理器检查表达式的计算结果是否为值



我使用的是gcc(特别是avr-gcc)。

这就是我的难题:

假设我在某个地方定义了这些:

#define THING_0_A 0
#define THING_0_B 1
#define THING_1_A 0

然后在第二个文件中,我有这个:

#define CONCAT_(A,B,C) A ## B ## C
#define CONCAT(A,B,C) CONCAT_(A,B,C)
#define ID 0
#define THING_N(A) CONCAT(THING_,ID,A)

有了这个,我现在有了一组表达式(仍在第二个文件中):

THING_N(_A) // evaluates to 0
THING_N(_B) // evaluates to 1
THING_N(_C) // evaluates to... nothing? Or undefined? Or THING_0_C?

现在,我想知道的是如何做到这一点(也仍然在第二个文件中):

#ifdef THING_N(_A)
    // Do something knowing that THING_N(_A) is defined (in this case THING_0_A)
#endif

或者:

#if THING_N(_A)
    // Do something knowing that the value THING_N(_A) evaluates to is defined and not just "nothing"
#endif

当然,这两种方法都不起作用,因为#ifdef不能将表达式作为参数(无论如何,它都会以"#ifdef0"结束),而THING_N(_A)在#if中的计算结果为0。

换句话说,我正在寻找一种使预处理器进行评估的方法:

THING_N(_A) to true
THING_N(_B) to true
THING_N(_C) to false
THING_N(_D) to false
etc...

在条件中使用。

试试这个:

#if (1-THING_N(_A)-1 != 2)

对于THING_N(_A)的每个值(除了值-2),这将是true。只有当THING_N(_A)未定义或定义为空时,它才会是false

如果您的宏有可能扩展到-2,您可以将第二个12修改为您选择的其他文字,以便基本思想成立。

您可以将值与已知值连接,并检查结果:

#define EMPTY_VAL_HELPER(VAL)  VAL ## 1
#define EMPTY_VAL(VAL)         EMPTY_VAL_HELPER(VAL)

现在你可以做:

#if defined(FOO) && (EMPTY_VAL(FOO) == 1)
//FOO is defined, but empty
#endif
#if defined(FOO) && (EMPTY_VAL(FOO) != 1)
//FOO is defined, and not empty
#endif

所以,在做了一系列研究和实验后,我得出结论,我的问题没有解决方案,原因其实很简单。

考虑到我在问题中的设置,这就是表达式的评估结果:

THING_N(_A) -> THING_0_A -> 0
THING_N(_B) -> THING_0_B -> 1
THING_N(_C) -> THING_0_C -> 0 (Not nothing, as I previously thought.)

我之前缺少的一条信息是,根据c99标准,未定义的标识符将被转换为0,而不是什么都没有,这使得无法区分未定义的和定义为0的。

如果c99标准选择让未定义的标识符求值为零,就像#define FOO让FOO求值为零一样,那么atturri的解决方案就会奏效。

哦,好吧。

最新更新