gcc 访问存储器地址0x0的内容将导致未定义的行为?

q35jwt9p  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(224)

我试图访问内存地址0,它被定义为ROM的起始地址,以检查我的配置是否正确以及该区域是否可访问。但当我编译代码时,产生的反汇编显示该操作未定义。
0确实是NULL并且可能被视为未定义,但是对于访问内存地址0处的内容,是否有任何解决方法?
下面是测试代码:

#include <stdio.h>
int main ()
{
    printf("%08X", *(unsigned int*)(0));
}

当用arm gcc和选项-Os编译时,得到反汇编结果。

main:
        mov     r3, #0
        ldr     r3, [r3]
        .inst   0xe7f000f0

可以看出,代码在.inst 0xe7f000f0处结束,并且printf未被调用。
该代码也可以在Compiler Explorer中找到。

x759pob2

x759pob21#

最简单的方法是通过链接器脚本Map绝对地址为零的对象,然后访问该对象,而不是尝试创建一个指向地址零的指针。
对于ARM Cortex M,工具链很可能已经为您完成了这一工作,其形式为向量表+地址0及以上的特殊寄存器。只需使用工具链提供的标识符,或者在不太可能出现的情况下,创建您自己的自定义链接器脚本,并在物理地址0分配变量。
至于问题中的“语言律师”部分:
0确实是NULL并且可能被视为未定义,但是对于访问内存地址0处的内容,是否有任何解决方法?
不完全是。NULL是一个空指针常量,0是一个空指针常量,这两个常量中的任何一个都可以用来创建空指针,就像在代码中将0转换为对象指针类型一样。
请参阅What's the difference between null pointers and NULL?,我试图澄清空指针、空指针常量和NULL宏之间的区别。
至于取消引用空指针,根据一元*运算符规范6.5.3/4,它 * 是 * 未定义的行为:
如果为指针分配了无效值,则一元*运算符的行为未定义

相关问题