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

Lau*_*tiu 9 c

由于我是C的新手,我必须使用以下一个项目:我必须声明一些全局变量,每次程序在相同的内存地址运行时都必须存储这些变量.我做了一些阅读,我发现我宣称它是"静态的"它将存储在同一个内存位置.

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

谢谢大家.Laurentiu

更新:我使用的是32uC

Lun*_*din 10

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

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

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

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

#define MY_REGISTER (*(volatile uint8_t*)0x12345678u)
Run Code Online (Sandbox Code Playgroud)

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

void func (void)
{
  MY_REGISTER = 1;  // write
  int var = MY_REGISTER;  // read
}
Run Code Online (Sandbox Code Playgroud)

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

void func (void)
{
  *(volatile uint8_t*)0x12345678u = 1; // write
  int var = *(volatile uint8_t*)0x12345678u; // read
}
Run Code Online (Sandbox Code Playgroud)

  • @Laurentiu"u"(或"U")后缀表示整数文字的类型为"unsigned".它是保证使用缩进类型,我写的主要是出于旧习惯.C源代码中的整数字面值默认为(signed)`int`类型,但由于地址永远不能为负数,因此使用带符号变量来存储它是没有意义的.通常,您永远不想在嵌入式系统中使用默认的`int`类型.在某些情况下,在进行简单算术时,您可能希望使用`sintN_t`类型,其中N = 8,16等.但大多数情况下,您只使用无符号变量. (2认同)
  • @Laurentiu您需要知道自己在做什么.除非链接器知道对象存储在该位置,否则什么都不会起作用.`"你必须阅读你的特定开发平台的文档","这不只是一个咨询声明,如果你不这样做并理解它,你的程序将无法正常工作. (2认同)

Ben*_*son 8

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

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

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