c - 直接内存映射 GCC 交叉编译
问题描述
我在 Windows 机器上为 ARM CortexA9 使用 gcc 交叉编译器,用于裸机应用程序。对于直接内存映射,我需要访问地址 0x8000_0000。我使用以下 C 代码:
#define PORTBASE_A 0x80000000
unsigned int volatile * const portA = (unsigned int *) PORTBASE_A;
#define PORTBASE_B 0x70000000
unsigned int volatile * const portB = (unsigned int *) PORTBASE_B;
#define PORTBASE_C 0x080000000
unsigned int volatile * const portC = (unsigned int *) PORTBASE_C;
printf("Portbase_A %p \n",(unsigned int *) portA); // Portbase_A 0xffffffff80000000
printf("Portbase_B %p \n",(unsigned int *) portB); // Portbase_B 0x70000000
printf("Portbase_C %p \n",(unsigned int *) portC); // Portbase_C 0xffffffff80000000
printf("%d\n", sizeof(unsigned int *)); //4
使用printf("Portbase_A %p \n",(unsigned int *) portA);
导致输出
Portbase_A 0xffffffff80000000
。
问题
尽管我的目标机器是 32 位机器,为什么我得到 64 位地址 (0xffffffff80000000)。我意识到在 0x8000_0000 中的前导位是一个,但是为什么这会导致 32 个前导位的 1 填充?这是由于交叉编译造成的某种人工制品吗?
非常感谢您的回复。
为了完整起见,这是我的分散文件的可视化。 分散文件可视化
解决方案
从标准的角度来看,根据C99: 6.3.2.3
报价:
5 整数可以转换为任何指针类型。除非前面指定,结果是实现定义的,可能没有正确对齐,可能不指向引用类型的实体,并且可能是一个陷阱表示。56)
由于结果是实现定义的,因此应该由实现来描述。IE。由编译器。关于指针的实现定义行为的 gcc 文档说:
将指针转换为整数或反之亦然的结果(C90 6.3.4、C99 和 C11 6.3.2.3)。
从指针到整数的强制转换 ....
如果指针表示小于整数类型,则从整数到指针的转换丢弃最高有效位,如果指针表示大于整数类型,则根据整数类型的符号进行扩展,否则位不变。
我假设(读作:猜测)在您的平台上:
- 二进制补码用于表示数字和指针
int
是 4 个字节- 所有指针都有 8 个字节
常量0x80000000
和0x70000000
类型都有int
。指针有 8 个字节。当您这样做时(unsigned int *)PORTBASE_A
,编译器必须将int
变量转换为 8 个字节。您的编译器生成执行二进制补码扩展的代码,即。int
转换为指针时,对于额外 4 个字节中的所有额外位重复最高有效位。因此,结果值的额外位设置为 1。
推荐阅读
- android - 为屏幕密度选择了错误的布局
- python - 既然 scipy.misc.imresize 已从 scipy 中删除,如何调整图像大小?
- controller - Rails 5.2:EventsController#new 中的 ActionController::ParameterMissing 用于嵌套资源
- javascript - 使用查询参数从 Firebase 获取产品ById
- angular - forkJoin 的成功回调没有被调用
- typescript - 检查字符串数组是否都是联合
- java - Android Studio - 录音问题 - Java 新手
- python-3.x - 升级到 3.8 后 distutils.util 丢失
- amazon-web-services - 如何在 LoadBalancers 中查找过时的策略
- gemfire - 选择用于 Geode 服务器和定位器启动脚本的参数的最佳策略是什么