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

use*_*356 4 c embedded

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

gbu*_*mer 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.

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

编译器可能会将const变量放入它们自己的内存段(gcc确实),这可能允许链接器(例如ld)脚本将它们放入闪存中,而不是为它们分配任何RAM(这不适用于例如使用的AVR ATmega)从闪存加载数据的不同构造.