我正在使用gcc交叉编译器在windows机器上的ARM CortexA9的裸露金属应用程序。对于直接内存映射,我需要访问地址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。
问题
为什么我得到64位地址(0xffffff800000),尽管我的目标机器是32位机器。我意识到在0x8000_0000中,领先位是一位,但是为什么这会导致32位的1填充呢?这是交叉比对造成的艺术品吗?
非常感谢您的回复。
为了完整起见,这是我的散乱文件的可视化。分散文件可视化
发布于 2019-12-13 18:04:37
从标准的角度来看,根据C99: 6.3.2.3的报价:
5整数可以转换为任何指针类型。除非如前所述,结果是实现定义的,可能没有正确对齐,可能没有指向被引用类型的实体,而且可能是陷阱表示。
由于结果是实现定义的,所以应该用实现来描述.即。由编译器完成。gcc关于实现指针定义行为的文档说:
将指针转换为整数的结果,反之亦然(C90 6.3.4、C99和C11 6.3.2.3)。 从指针到整数的转换. 从整数到指针的转换如果指针表示小于整数类型,则丢弃最重要的位;如果指针表示大于整数类型,则根据整数类型的签名性进行扩展,否则比特不变。
我假设(阅读为:猜测)在您的平台上:
int是4个字节常量0x80000000和0x70000000都具有int类型。指针有8个字节。当您执行(unsigned int *)PORTBASE_A时,编译器必须将一个int变量转换为8个字节。编译器生成执行两个补号延拓的代码,即。当从int转换到指针时,对额外4字节中的所有额外位重复最重要的位。正因为如此,结果值将额外的位设置为1。
https://stackoverflow.com/questions/59327625
复制相似问题