在 C++ 中,是否可以创建从特定地址(例如 0x1000)开始的特定大小的数组(例如短数组 [2048])?
5 回答
在嵌入式系统中,您可以使用链接器文件在此处映射符号或特殊段。或者可能是一个pragma。这对于嵌入式系统来说是很常见的事情,其中引导加载程序需要与其启动的应用程序共享内存空间,或者协处理器在固定地址与主 CPU 具有共享内存库。问题是方法因工具而异。
简短回答:不。在非嵌入式系统中(我将对此进行限制),用户地址空间是虚拟地址空间。这意味着即使你得到一个指向 0x1000 的指针,它也不是你在物理内存映射中分配的数据的物理位置。因此,由于系统对您隐藏了物理地址 - 您无法请求特定的物理地址。然而,虚拟地址是不同的故事......
了解了指向 0x1000 并不能保证实际上意味着您指向的是物理地址0x1000,在 Linux 中,您可以使用该函数mmap()
及其 Windows 对应函数VirtualAlloc()
来请求分配给特定的虚拟地址。当然,这些功能不能保证正常工作(例如,如果您请求的虚拟地址已经被映射,或者它是系统“保留”的)。
可以使用placement new:
struct A { short array[2048]; };
char *addr = (char*)0x1000;
new (addr) A;
如果您想要动态大小,请使用以下内容:
new (addr) short[size];
假设一个嵌入式系统,你的问题确实有道理。
通常,您可以通过定义具有寄存器大小的易失性指针来访问外设的内存映射寄存器。然而,由于这种方法很常见,因此一旦涉及 MISRA 或 CERT C 等编码标准,它就有一个缺点。这些标准声称指针在一般的安全关键系统中是危险的东西。因此,您应该尽可能避免使用它们。
当我偶然发现这个问题一段时间时,似乎有像ARM 所述的“更好”的方法可用(将变量映射到特定地址)。您必须在自己的编译单元中定义结构/数组(结果是单个 .o 文件)。在此之后,您需要编写一个链接器文件,将这个单个 .o 文件放在指定的地址。
如果您想要一个特定地址的数组,您可以将它放在一个结构中,然后您可以分配一个指向所需位置的指针。看这个例子:
struct A {
short array[2048];
};
int main(char argc, char** argv) {
A* a = (A*)0x1000;
printf("%p\n", &a->array[0]);
return 0;
}