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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15267001/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:36:50  来源:igfitidea点击:

How to store a variable at a specific memory location?

c

提问by Laurentiu

As i am relatively new to C , i have to use for one of my projects the following: i must declare some global variables which have to be stored every time the program runs at the same memory address. I did some read and i found that is i declare it "static" it will be stored at the same memory location.

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

But my question is: can i indicate the program where to store that variable or not. For example : int a to be stored at 0xff520000. Can this thing be done or not? i have searched here but did not found any relevant example. If their is some old post regarding this, please be so kind to share the link .

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

Thank you all in advance. Laurentiu

谢谢大家。劳伦修

Update: I am using a 32uC

更新:我使用的是 32uC

回答by Lundin

In your IDE there will be a memory map available through some linker file. It will contain all addresses in the program. Read the MCU manual to see at which addresses there is valid memory for your purpose, then reserve some of that memory for your variable. You have to read the documentation of your specific development platform.

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

Next, please note that it doesn't make much sense to map variables at specific addresses unless they are either hardware registers or non-volatile variables residing in flash or EEPROM.

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

If the contents of such a memory location will change during execution, because it is a register, or because your program contains a bootloader/NVM programming algorithm changing NVM memory cells, then the variables mustbe declared as volatile. Otherwise the compiler will break your code completely upon optimization.

如果此类存储器位置的内容在执行期间会发生更改,因为它是寄存器,或者因为您的程序包含更改 NVM 存储器单元的引导加载程序/NVM 编程算法,则必须将变量声明为易失性。否则编译器会在优化时完全破坏你的代码。

The particular compiler most likely has a non-standard way to allocate variables at specific addresses, such as a #pragma or sometimes the weird, non-standard @operator. The only sensible way you can allocate a variable at a fixed location in standard C, is this:

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

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

where 0x12345678 is the address where 1 byte of that is located. Once you have a macro declaration like this, you can use it as if it was a variable:

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

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

Most often you want these kind of variables to reside in the global namespace, hence the macro. But if you for some reason want the scope of the variable to be reduced, then skip the macro and access the address manually inside the code:

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

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

回答by Ben Hymanson

You can do this kind of thing with linker scripts, which is quite common in embedded programming.

你可以用链接脚本来做这种事情,这在嵌入式编程中很常见。

On a Linux system you might never get the same virtual address due to address space randomization (a security feature to avoid exploits that would rely on knowing the exact location of a variable like you describe).

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

If it's just a repeatable pointer you want, you may be able to map a specific address with mmap, but that's not guaranteed.

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

回答by SomeWittyUsername

Like was mentioned in other answers - you can't. But, you can have a workaround. If it's ok for the globals to be initialized in the main(), you can do something of this kind:

就像在其他答案中提到的一样 - 你不能。但是,您可以有一个解决方法。如果可以在 中初始化全局变量main(),您可以执行以下操作:

int addr = 0xff520000;

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

Note, however, that this is very dependent on your system and if running in protected environment, you'll most likely get a runtime crash. If you're in embedded/non-protected environment, this can work.

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

回答by Tony The Lion

No you cannot tell it explicitly where to store a variable in memory. Mostly because on modern systems you have many things done by the system in regards to memory, that is out of your control. Address Layout Randomization is one thing that comes to mind that would make this very hard.

不,您不能明确告诉它在内存中存储变量的位置。主要是因为在现代系统上,系统可以完成许多有关内存的工作,这是您无法控制的。地址布局随机化是一件事,这会让这变得非常困难。

回答by luser droog

Not at the C level. If you work with assembly language, you can directly control the memory layout. But the C compiler does this for you. You can't really mess with it.

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

Even with assembly, this only controls the relative layout. Virtual memory may place this at any (in)convenient physical location.

即使是装配,这也只能控制相对布局。虚拟内存可以将其放置在任何(不)方便的物理位置。

回答by Art

You can do this with some compiler extensions, but it's probably not what you want to do. The operating system handles your memory and will put things where it wants. How do you even know that the memory address you want will be mapped in your program? Ignore everything in this paragraph if you're on an embedded platform, then you should read the manual for that platform/compiler or at least mention it here so that people can give a more specific answer.

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

Also, static variables don't necessarily have the same address when the program runs. Many operating systems use position independent executables and randomize the address space on every execution.

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

回答by SteveP

You can declare a pointer to a specific memory address, and use the contents of that pointer as a variable I suppose:

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

int* myIntPointer = 0xff520000;