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

时间:2012-03-23 02:48:44

标签: c embedded

如果我在嵌入式系统中定义宏,或使用静态const值,则 将使用哪种内存,芯片闪存或芯片内存? 哪种方式更好?

3 个答案:

答案 0 :(得分:16)

我相信答案更复杂。

编辑:我为使用'should'和'might'道歉,但没有特定的编译器或调试器,我发现它必须准确和准确。也许如果问题可以说明目标是什么编译器和平台,我们可以更清楚了吗?

  1. #define NAME ((type_cast)value)在代码中显示之前不会占用任何空间。编译器可能能够使用其值来推断某些东西(与使用具有未知运行时值的变量相比),因此可能会更改生成的代码,使其有效地不占用空间,甚至可能减小代码的大小。如果编译器的分析是在运行时需要文字值,那么它会占用代码空间。字面值是已知的,因此编译器应该能够分配最佳空间量。根据处理器的不同,它应该存储在闪存中,但可能不是内联代码,而是在“文字池”中,一组局部变量,通常靠近代码,因此可以使用紧凑的地址。编译器可能会做出正确的决定。

  2. static const type name = value;在代码中使用之前不应占用空间。即使它在代码中使用,它可能会或可能不会消耗“空间”,具体取决于您的编译器(我认为,它正在编译的C标准)以及代码如何使用该值。

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

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

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

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

  3. 还有第三种方法,即使用枚举:

    enum CONSTANTS {name = 1234,height = 456 ...};

    编译器可能会对这些问题进行处理,例如#define constants,尽管它们不够灵活,因为它们的大小为int(IIRC)。无法获取枚举值的地址,因此编译器可以使用尽可能多的选项来生成#define NAME的良好代码。它们通常在调试器中可用。

  4. const type name = value;可能会消耗RAM。它必须在内存中,因为编译器无法知道不同文件中的代码是否使用它,或者获取其地址(但gcc LTO可能会改变它)const告诉编译器'警告'(或'错误)任何代码尝试使用赋值运算符更改值e,g。通常,RAM中保存的变量存储在数据或bss内存段中。默认情况下,gcc将const放入只读段,该段可以使用命令行选项-mrodata= readonly-data-section 进行设置。该段是ARM上的.rodata。

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

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

答案 1 :(得分:3)

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

如果使用static const全局变量,将生成二进制代码以获取初始值和为其分配的内存。使用flash(bin文件大小更大)和内存(chip ram)。

答案 2 :(得分:2)

除了其他说法:

  1. 使用#define不会告诉变量。定义自己不需要任何东西,但是如果你做了类似int x = MY_DEFINE的东西,它当然会使用一个,它将是非常量的。
  2. 在某些工具链/系统上,您实际上可以将const变量放入某个特殊部分,您可以放入FLASH / ROM,通常使用自定义链接描述文件/编译器开关。