首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >const value与#define,将使用哪种芯片资源?

const value与#define,将使用哪种芯片资源?
EN

Stack Overflow用户
提问于 2012-03-23 10:48:44
回答 3查看 1.9K关注 0票数 4

如果我在嵌入式系统中定义宏或使用静态常量值,

将使用哪种存储器,芯片闪存还是芯片ram?哪种方式更好?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-23 10:54:38

好吧,如果你#定义一个宏,没有额外的内存或代码空间(flash)分配给它。所有工作都在编译阶段完成。

如果使用static const全局变量,将为初始值和为其分配的内存生成二进制代码。使用闪存(bin文件较大)和内存(芯片ram)。

票数 3
EN

Stack Overflow用户

发布于 2012-03-23 12:18:50

我相信答案会更复杂。

编辑:我很抱歉使用了“应该”和“可能”,但没有特定的编译器或调试器,我发现它必须准确和精确。也许如果问题可以说出目标是什么编译器和平台,我们就可以更清楚?

在出现在代码中之前,

  1. #define NAME ((type_cast)value)不会占用任何空间。编译器可能能够使用它的值来推断某些东西(与使用具有未知运行时值的变量相比),因此可能会更改生成的代码,从而有效地不消耗任何空间,或者甚至可以减少代码的大小。如果编译器的分析是在运行时需要该字面值,那么它将消耗代码空间。字面值是已知的,因此编译器应该能够分配最佳的空间量。根据处理器的不同,它应该存储在闪存中,但可能不是内联代码,而是在“文字池”中,一组本地变量,通常靠近代码,因此可以使用紧凑的地址。编译器可能会使良好的decisions.
  2. static const type name = value;在代码中使用之前不会消耗空间。即使在代码中使用它,它也可能消耗“空间”,也可能不消耗“空间”,这取决于您的编译器(我认为是它正在编译的C标准)以及代码如何使用该值。

如果名称的地址从未被获取过,那么编译器就不必存储它。如果该值的地址被获取(并且该代码没有被删除),则该值一定在内存中。智能编译器将检测源文件中是否有任何代码采用其地址。即使它可能被存储,编译器也可能通过不使用存储值来生成更好的(更快或更紧凑的代码)。

尽管编译器可能比#define更糟糕,但它可能会做得和#define NAME一样好。

如果该值的地址已取,则编译器将该变量视为已初始化的变量,这将消耗空间来存储常量值。编译器并不真正将值放入RAM或闪存中。这取决于链接器。在gcc中,有一些“属性”可以用来告诉链接器应该将变量放到哪个段中。默认情况下,编译器将初始化的变量放入缺省数据段,并将const初始化放入只读段。通过使用属性,程序员可以将变量放入任何段中。使用适当的链接器脚本(通常随工具链一起提供),片段可以放入flash中。对于文字字符串之类的数据,Gcc使用只读数据段。

name应该在调试器中可用,但#define NAME不能。

  • 还有第三种方法,就是使用枚举的:

枚举常量{ name = 1234,height = 456 ... };

这些可能会被像#define constants这样的编译器处理,尽管它们不是很灵活,因为它们是int大小(IIRC)。没有办法获取枚举值的地址,因此编译器有许多选项来生成良好的代码和#define NAME。它们通常会在debugger.

  • const type name = value;中可用,可能会消耗内存。它必须在内存中,因为编译器无法知道其他文件中的代码是否使用了它,或者是否获取了它的地址(但gcc LTO可能会改变这一点)。const告诉编译器,如果任何代码试图更改值,就会发出警告(或错误),例如,使用赋值操作符。通常,内存中保存的变量存储在数据段或bss内存段中。默认情况下,gcc将数据段放入只读段,可以使用命令行选项-mrodata= const --mrodata=- .rodata来设置该段。该段在ARM上是.rodata。

在嵌入式系统中,所有初始化的全局变量和静态变量(无论是否为const)都保存在闪存中,并在程序启动时(在调用main()之前)复制到内存中。在调用main()之前,所有未初始化的全局变量或静态变量都设置为0。

编译器可能会将const变量放入它们自己的内存段(gcc就是这样做的),这可能会允许链接器(例如ld)脚本将它们放入闪存,而不会为它们分配任何内存(这在使用不同指令从闪存加载数据的AVR ATmega上不起作用)。

票数 17
EN

Stack Overflow用户

发布于 2012-03-23 15:32:42

除了其他人所说的:

使用#define的

  1. 不会告知任何有关变量的信息。Define本身不需要任何常量变量,但是如果你做类似int x= MY_DEFINE的事情,它当然会使用一个常量变量,而且它将是非常量的。
  2. 在一些工具链/系统上,你实际上可以将常量变量放入一些特殊的部分,你可以放入闪存/只读存储器,通常使用自定义的链接器脚本/编译器开关。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9833514

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档