我怎样才能让 gcc 预处理器检查一个表达式的计算结果是一个值还是什么都没有?
How can I get the gcc preprocessor to check if an expression evaluates to a value or nothing?
我正在使用 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 不能将表达式作为参数(无论如何它最终都会成为“#ifdef 0”),并且 THING_N(_A) 的计算结果为 0在#if.
内
换句话说,我正在寻找一种让预处理器求值的方法:
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
,您可以将第二个 1
和 2
修改为您选择的其他文字,以便基本思想成立.
您可以将值与已知值连接,并检查结果:
#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 的解决方案就会起作用。
好吧。
我正在使用 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 不能将表达式作为参数(无论如何它最终都会成为“#ifdef 0”),并且 THING_N(_A) 的计算结果为 0在#if.
内换句话说,我正在寻找一种让预处理器求值的方法:
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
,您可以将第二个 1
和 2
修改为您选择的其他文字,以便基本思想成立.
您可以将值与已知值连接,并检查结果:
#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 的解决方案就会起作用。
好吧。