在C预处理器中比较常量指针遇编译错误,求可行解决方法
编译时比较GPIO指针宏报错的解决方法
问题背景代码
gpios.h
#define GPIO_BASE 0x08000100 #define GPIOA ((GpioRegs *) (GPIO_BASE + 0x04)) #define GPIOB ((GpioRegs *) (GPIO_BASE + 0x0C)) #define GPIOC ((GpioRegs *) (GPIO_BASE + 0x14))
switches.h
#define SWITCH1_PORT GPIOA // On this particular system, both switches #define SWITCH2_PORT GPIOA // are on the same port. This could change in the future
switches.c
#if SWITCH1_PORT == SWITCH2_PORT // Code is a lot simpler if both switches are on the same port #else // Otherwise do it the hard way #endif
报错信息
gpios.h:772:45: error: operator '*' has no right operand 772 | #define GPIOA ((GpioReg *) (GPIO_BASE + 0x04)) | ^ switches.h:102:33: note: in expansion of macro 'GPIOA' 102 | #define SWITCH1_PORT GPIOA | ^~~~~ switches.c:172:5: note: in expansion of macro 'SWITCH1_PORT' 172 | #if SWITCH1_PORT == SWITCH2_PORT | ^~~~~~~~~~~~
解决方案
问题根源是C预处理器只做文本替换,无法识别(GpioRegs *)这种C语法的类型转换,预编译阶段处理==比较时会把类型转换当成无效语法,从而报错。这里提供两种可靠解决方法:
方法一:分离地址数值与指针宏(兼容性最优)
把端口的纯地址数值和指针宏分开定义,用数值做预编译比较,指针宏保留供业务代码使用:
- 修改gpios.h:
#define GPIO_BASE 0x08000100 // 先定义纯数值的端口地址 #define GPIOA_ADDR (GPIO_BASE + 0x04) #define GPIOB_ADDR (GPIO_BASE + 0x0C) #define GPIOC_ADDR (GPIO_BASE + 0x14) // 基于地址数值定义指针宏 #define GPIOA ((GpioRegs *) GPIOA_ADDR) #define GPIOB ((GpioRegs *) GPIOB_ADDR) #define GPIOC ((GpioRegs *) GPIOC_ADDR)
- 修改switches.h:
// 用数值地址宏定义端口标识,用于预编译比较 #define SWITCH1_PORT_ADDR GPIOA_ADDR #define SWITCH2_PORT_ADDR GPIOA_ADDR // 保留原有指针宏,不影响业务代码使用 #define SWITCH1_PORT GPIOA #define SWITCH2_PORT GPIOA
- 修改switches.c的预编译判断:
#if SWITCH1_PORT_ADDR == SWITCH2_PORT_ADDR // Code is a lot simpler if both switches are on the same port #else // Otherwise do it the hard way #endif
这种方式让预处理器处理纯数值比较,完全符合预编译语法规则,兼容性拉满。
方法二:用uintptr_t强制转换(需C99支持)
如果编译器支持C99标准,可以用uintptr_t类型把指针转换成整数再比较,注意要包含<stdint.h>:
#include <stdint.h> #if (uintptr_t)SWITCH1_PORT == (uintptr_t)SWITCH2_PORT // Code is a lot simpler if both switches are on the same port #else // Otherwise do it the hard way #endif
这种方式无需修改原有宏定义,但依赖编译器对uintptr_t的支持,兼容性略逊于方法一。
内容的提问来源于stack exchange,提问作者Edward Falk
相关产品推荐
相关产品推荐

