静态变量存储在哪里?

电器工程 嵌入式 C
2022-01-22 03:18:37

假设我使用的是 8051。我编译了一个具有静态变量的代码。该静态变量将存储在哪里?在内存中?在堆栈中?在堆上??闪现?在哪里?

另外,如果我错了,请纠正我:常量存储在 ROM 中。并且全局变量存储在 Flash 中。(如果我没有 Flash 怎么办?)

我期待有关嵌入式编程的答案。它不像在代码段或 .bss 中,而是在我的板上的确切位置?

4个回答

假设我使用的是 8051。

那么你应该了解CODE、DATA、IDATA、XDATA和PDATA内存——8051是一个多哈佛架构。

该静态变量将存储在哪里?

这是个好问题。这取决于编译器设置——通常称为“内存模型”;但是您也可以明确说明编译器会将其放在哪里:

xdata unsigned int i;  // integer in XDATA memory

编译器/链接器应该能够创建一个 Map 文件,它将向您显示变量的地址。

常量存储在 ROM 中。

这可能取决于编译器,需要对照 Map 文件进行检查。我记得明确标记了这些:

code const char fooStr[]="Foo";  // string constant in code = flash memory

并且全局变量存储在Flash中

无论真假。它们驻留在 8051 的数据存储器之一中,但初始值将在启动时从 Flash 加载 - 除非变量初始化为零。

以下答案基于我查看地图文件的经验,如果我对某事有误。请纠正我!

静态变量绝对不会存储在堆上,因为这仅适用于在运行时分配的变量(静态变量是在编译时分配的)。

静态变量存储在 RAM 中,就像您的全局变量一样。某个变量的范围只对编译器很重要,在机器代码级别,没有人阻止您读取函数之外的局部变量(只要您的控制器没有一些花哨的功能来保护内存区域不被访问) .

并且全局变量存储在 Flash 中。

不。想一想:要写入一个闪存,您必须擦除整个数据块,然后用修改后的数据重写整个数据。并且这些步骤不像简单的存储到 RAM 那样在单个周期中执行。就像前面提到的,全局变量存储在 RAM 中。这也解决了您对无闪存系统的困惑。

在代码存储与所有其他变量位于同一地址空间的处理器上,编译器通常会将“const”限定的全局或静态变量放入它们自己的链接部分,并且链接器通常会配置为将该部分放置在系统代码中存储(闪存、OTP 或其他)。这将减少程序所需的 RAM 量,并减少启动代码必须执行的工作量。

在代码存储位于不同地址空间的处理器上(例如 PIC 或 8051),一些编译器将使用const限定符来表示它们应该将变量放入代码存储并使用不同的指令来访问它们,而其他编译器则不会. 这样的编译器将要求只能使用带有const限定符的指针来访问const-declared 变量,因为没有该要求,编译器将不知道必须使用特殊指令来访问此类指针。

在我见过的 8051 编译器(阿基米德和 Keil)上,有 8051 编译器特定的关键字 __data、__idata、__code、__bdata、_pdata_xdata 可用于指示变量应加载到特定地址空间中。默认情况下,名称可以带或不带下划线;非下划线版本更方便,但如果移植一个使用名为codeor的标识符的程序,则可能会被禁用data如果在声明指针时未将这些关键字之一应用于其目标,则编译器将分配三个字节:一个指示目标所在的内存空间,两个用于保存 16 位地址(如果需要)。声明一个变量const而不应用codequalifier 将导致变量放置在默认 RAM 地址空间中,并在启动时加载默认值;以这种方式声明的变量可能会被传递给期望默认地址空间中的指针的代码(但将使用 RAM)。添加__code(或code,如果启用)声明将导致变量被放置在代码空间中。使用声明通常code比不使用要好,但在某些情况下,特别是如果所讨论的项目很小,访问idataRAM 中的内容的相对容易性可能会弥补该空间的几个字节的损失。

部分答案:“另外,如果我错了,请纠正我:CONST 存储在 ROM 中。”

不正确。关键字“const”是帮助编译器的指令。当一个变量被声明为“const”时,编译器知道它不能改变,但它仍然是一个分配了内存位置的变量。

如果您需要/想要将其存储在 ROM 中,那么您将需要为编译器使用另一个关键字,告诉它要使用哪种内存类型或位置。我不认为有一个标准化的关键字。可能是因为 C 在 PC 上开始使用,所有程序空间和变量空间都是 RAM。

对于 PIC,您将在声明变量时使用关键字“rom”。

例如“rom int const x = 42;”