如何将变量存储在特定的内存位置?

时间:2013-03-07 09:07:43

标签: c

由于我对C比较陌生,我必须使用以下一个项目: 我必须声明一些全局变量,每次程序在同一个内存地址运行时都必须存储这些变量。 我做了一些阅读,我发现这是我声明它“静态”它将存储在相同的内存位置。

但我的问题是:我可以指出程序在哪里存储该变量。 例如:int a存储在0xff520000。这件事可以做到吗?我在这里搜索过,但没有找到任何相关的例子。如果他们是关于此的一些旧帖子,请非常友好地分享链接。

提前谢谢大家。 Laurentiu

更新:我使用的是32uC

8 个答案:

答案 0 :(得分:10)

在IDE中,将通过某个链接器文件提供内存映射。它将包含程序中的所有地址。阅读MCU手册,了解哪些地址有效存储器用于您的目的,然后为您的变量保留一些内存。您必须阅读特定开发平台的文档。

接下来,请注意,将变量映射到特定地址没有多大意义,除非它们是硬件寄存器或驻留在闪存或EEPROM中的非易失性变量。

如果这样的内存位置的内容在执行期间会发生变化,因为它是一个寄存器,或者因为你的程序包含一个改变NVM内存单元的bootloader / NVM编程算法,那么变量必须宣称为不稳定。否则,编译器将在优化时完全破坏您的代码。

特定编译器很可能采用非标准方式在特定地址分配变量,例如#pragma或有时候是奇怪的非标准@运算符。您可以在标准C中的固定位置分配变量的唯一合理方法是:

#define MY_REGISTER (*(volatile uint8_t*)0x12345678u)

其中0x12345678是其中1个字节所在的地址。一旦你有这样的宏声明,就可以像使用它一样使用它:

void func (void)
{
  MY_REGISTER = 1;  // write
  int var = MY_REGISTER;  // read
}

大多数情况下,您希望这些变量驻留在全局命名空间中,因此也就是宏。但是如果你出于某种原因想要减少变量的范围,那么跳过宏并在代码中手动访问地址:

void func (void)
{
  *(volatile uint8_t*)0x12345678u = 1; // write
  int var = *(volatile uint8_t*)0x12345678u; // read
}

答案 1 :(得分:8)

您可以使用链接器脚本执行此类操作,这在嵌入式编程中非常常见。

在Linux系统上,由于地址空间随机化,您可能永远不会获得相同的虚拟地址(这是一种安全功能,可以避免依赖于了解您所描述的变量的确切位置的漏洞)。

如果它只是您想要的可重复指针,您可以使用mmap映射特定地址,但这不能保证。

答案 2 :(得分:1)

不,你不能明确告诉它在内存中存储变量的位置。主要是因为在现代系统中,系统在内存方面做了很多事情,这是你无法控制的。地址布局随机化是我想到的一件事,这会使这很难。

答案 3 :(得分:1)

就像在其他答案中提到的那样 - 你不能。 但是,你可以有一个解决方法。如果可以在main()中初始化全局变量,那么你可以做一些这样的事情:

int addr = 0xff520000;

int main()
{
    *((int*)addr) = 42;
    ...
    return 0;
}

但请注意,这非常依赖于您的系统,如果在受保护的环境中运行,您很可能会遇到运行时崩溃。如果您处于嵌入式/非受保护环境中,则可以正常工作。

答案 4 :(得分:1)

根据您的编译器(如果您使用XC8编译器)。 只需将int x @ 0x12写入即可;

在此行中,将x设置在内存位置0x12

答案 5 :(得分:0)

不在C级。如果使用汇编语言,则可以直接控制内存布局。但是C编译器会为你做这件事。你真的不能搞砸它。

即使使用汇编,这也仅控制相对布局。虚拟内存可以将其放置在任何(在)方便的物理位置。

答案 6 :(得分:0)

您可以使用某些编译器扩展来执行此操作,但这可能不是您想要执行的操作。操作系统处理您的内存并将其放置在所需的位置。你怎么知道你想要的内存地址将被映射到你的程序中?如果您在嵌入式平台上,请忽略本段中的所有内容,然后您应该阅读该平台/编译器的手册或至少在此处提及,以便人们可以提供更具体的答案。

此外,程序运行时,静态变量不一定具有相同的地址。许多操作系统使用与位置无关的可执行文件,并在每次执行时随机化地址空间。

答案 7 :(得分:0)

您可以声明指向特定内存地址的指针,并将该指针的内容用作我认为的变量:

int* myIntPointer = 0xff520000;