Closed. This question needs details or clarity. It is not currently accepting answers. Learn more。
想改进这个问题吗?添加细节并通过editing this post澄清问题。
去年关门了。
对于微控制器,我使用宏作为HAL。现在,为了概括哈尔的用法,我想做一些
然而,UART1是具有类型转换(e.x.
我举了一个简单的例子:
它也无法与gcc一起编译,并带有以下注释:
但是,如果删除v1和v2定义中的(double),它将按预期编译并运行。
注意,作为另一种解决方案
但这涉及到另一个变量[编辑:技术上是一个宏,但实际上是另一组我必须跟踪的字符]。
我很想知道编译错误背后的原因和/或如何解决它,如果可能的话。
因为
实际上你在比较-
由于语法错误,它不是有效的常量表达式。
当我用我的编译器运行这个时,我得到
错误:令牌不是预处理器子表达式中的有效二进制运算符
你提到的解决办法似乎是个好办法。您不应该担心“但它涉及另一个变量”,因为这些不是变量而是宏。宏是编译时实体,不会以任何方式增加运行时的负担(内存、寄存器压力甚至执行时间)。
想改进这个问题吗?添加细节并通过editing this post澄清问题。
去年关门了。
对于微控制器,我使用宏作为HAL。现在,为了概括哈尔的用法,我想做一些
#define UART UART1
#if UART==UART1
# define PIN_TX 9
#elif UART==UART2
# define PIN_TX 2
#else
# warning "UART not correctly defined"
#endif
然而,UART1是具有类型转换(e.x.
(uint8_t*)0x004000000
)的内存地址。所以编译器会打印一些错误。我举了一个简单的例子:
#include <stdio.h>
#define v1 (double)1
#define v2 (double)2
int main(int argc, char *argv[])
{
printf("We have: ");
#define VAL (v1)
#if VAL==v1
printf("VAL is 1\n");
#elif VAL==v2
printf("VAL is 2\n");
#else
# warning "VAL not 1 or 2"
printf("Not defined\n");
#endif
}
它也无法与gcc一起编译,并带有以下注释:
cc preproc.c -o preproc
preproc.c: In function ‘main’:
preproc.c:3:20: error: missing binary operator before token "1"
#define v1 (double)1
^
preproc.c:10:14: note: in expansion of macro ‘v1’
#define VAL (v1)
^~
preproc.c:12:5: note: in expansion of macro ‘VAL’
#if VAL==v1
^~~
preproc.c:3:20: error: missing binary operator before token "1"
#define v1 (double)1
^
preproc.c:10:14: note: in expansion of macro ‘v1’
#define VAL (v1)
^~
preproc.c:14:7: note: in expansion of macro ‘VAL’
#elif VAL==v2
^~~
preproc.c:17:2: warning: #warning "VAL not 1 or 2" [-Wcpp]
#warning "VAL not 1 or 2"
^~~~~~~
<builtin>: recipe for target 'preproc' failed
make: *** [preproc] Error 1
但是,如果删除v1和v2定义中的(double),它将按预期编译并运行。
注意,作为另一种解决方案
#define USE_UART1
//#define USE_UART2
#if defined(USE_UART1)
# define UART UART1
# define PIN_TX 9
#elif defined(USE_UART2)
# define UART UART2
# define PIN_TX 2
#else
# warning "UART not correctly defined"
#endif
但这涉及到另一个变量[编辑:技术上是一个宏,但实际上是另一组我必须跟踪的字符]。
我很想知道编译错误背后的原因和/或如何解决它,如果可能的话。
最佳答案
引用C11
,章节§6.10.1p4
在求值之前,将成为控制常量表达式的预处理标记列表中的宏调用将被替换(由定义的一元运算符修改的宏名称除外),就像在普通文本中一样。如果定义的令牌是由此替换过程生成的,或者在宏替换之前使用的已定义一元运算符与指定的两个窗体之一不匹配,则行为未定义。在执行了由于宏扩展和定义的一元运算符的所有替换之后,所有剩余的标识符(包括那些与关键字相同的词汇)被替换为PP编号0,然后每个预处理令牌被转换为令牌。...
在您的代码中,您正在比较-
#if ((double)1)==((double)1)
因为
double
不是一个有效的标记,所以它被(0)
替换。实际上你在比较-
#if ((0)1)==((0)1)
由于语法错误,它不是有效的常量表达式。
当我用我的编译器运行这个时,我得到
错误:令牌不是预处理器子表达式中的有效二进制运算符
你提到的解决办法似乎是个好办法。您不应该担心“但它涉及另一个变量”,因为这些不是变量而是宏。宏是编译时实体,不会以任何方式增加运行时的负担(内存、寄存器压力甚至执行时间)。
关于c - C具有扩展宏和类型转换的条件预处理器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50409090/
10-15 04:42