GCC Macro 1 + 1不等于2?

Dan*_*ine 1 c macros gcc

我正在定义使用GCC进行编译的Tiva C系列Launchpad的寄存器.

在头文件中我有如下代码:

样品A.

#define GPIOB_BASE 0x40005000
#define GPIOB_AFSEL_R (*((unsigned long *) GPIOB_BASE + 0x420))
#define GPIOB_DEN_R (*((unsigned long *) GPIOB_BASE + 0x51C)) 
#define GPIOB_PCTL_R (*((unsigned long *) GPIOB_BASE + 0x52C))
Run Code Online (Sandbox Code Playgroud)

为了检查它是否正在按照我的想法进行操作,我编写了这个小程序并按预期返回"10".我继续我的项目,并迅速遇到硬故障的大问题(写入不可写的地址).

宏测试

#include <stdio.h>

#define BASE 0x9
#define BASE + PLUS_ONE 0x01

int main(void){
    printf("%d", PLUS_ONE);
}
Run Code Online (Sandbox Code Playgroud)

经过几个小时的拉动我的头发试图调试,我最终用硬编码的等价物替换了地址.

样品B.

#define GPIOB_BASE 0x40005000
#define GPIOB_AFSEL_R (*((unsigned long *) 0x40005420))
#define GPIOB_DEN_R (*((unsigned long *) 0x4000551C))
#define GPIOB_PCTL_R (*((unsigned long *) 0x4000552C))
Run Code Online (Sandbox Code Playgroud)

硬故障消失了,事情开始起作用了!

有人可以帮我理解样品A和样品B之间的区别吗?

(是的,我应该更加关注生成的汇编代码)

unw*_*ind 11

指针算术不是以字节为单位完成的,它是以指向的对象为单位完成的.

在你的情况下,unsigned long.所以这:

 ((unsigned long *) GPIOB_BASE + 0x420
Run Code Online (Sandbox Code Playgroud)

将导致地址0x40005000 + 0x420*sizeof (unsigned long).假设一个32位long,那就是0x40006080,这显然不是你想要的.

你应该把宏写成

#define GPIOB_AFSEL_R (*(unsigned long *) (GPIOB_BASE + 0x420))
Run Code Online (Sandbox Code Playgroud)

现在,在将结果转换为指针并取消引用之前,在两个整数之间添加.多赢了.