const value vs.#define,将使用哪种芯片资源?

const value vs.#define,将使用哪种芯片资源?,c,embedded,C,Embedded,如果在嵌入式系统中定义宏或使用静态常量值, 将使用哪种内存,芯片闪存还是芯片ram? 哪种方法更好?好吧,如果你定义一个宏,就不需要为它分配额外的内存或代码空间(flash)。所有工作都在编译阶段完成 如果使用静态常量全局变量,将为初始值生成二进制代码并为其分配内存。使用闪存(bin文件大小更大)和内存(芯片ram)。我认为答案更复杂 编辑:我为使用“应该”和“可能”道歉,但没有特定的编译器或调试器,我发现它必须准确无误。也许如果这个问题能说明编译器和平台的目标是什么,我们就能更清楚了 #定义名

如果在嵌入式系统中定义宏或使用静态常量值,
将使用哪种内存,芯片闪存还是芯片ram? 哪种方法更好?

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


如果使用
静态常量
全局变量,将为初始值生成二进制代码并为其分配内存。使用闪存(bin文件大小更大)和内存(芯片ram)。

我认为答案更复杂

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

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

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

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

    编译器的工作可能与
    #define NAME
    一样好,尽管可能比
    #define

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

    name
    应该在调试器中可用,但
    #define name
    将不可用

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

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

    编译器可以像对待
    #define constants
    一样对待它们,尽管它们没有那么灵活,因为它们是
    int
    size(IIRC)。无法获取枚举值的地址,因此编译器有尽可能多的选项来生成好的代码和定义名称。它们通常在调试器中可用

  • const type name=value可能会消耗RAM。它必须在内存中,因为编译器无法知道不同文件中的代码是否使用它,或者获取其地址(但gcc LTO可能会改变),因此
    const
    告诉编译器在任何代码试图使用赋值操作符更改值(例如,g)的情况下,发出警告(或“错误”)。通常,RAM中保存的变量存储在数据或bss内存段中。默认情况下,gcc将
    const
    放入只读段,该段可以使用命令行选项
    -mrodata=
    只读数据段进行设置。那部分是手臂上的罗达

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


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

    除了其他人所说的以外:

  • 使用#define对变量没有任何说明。定义本身不需要任何东西,但是如果你做一些像int x=MY_Define这样的事情,它当然会使用一个,它将是非常量的
  • 在某些工具链/系统上,您实际上可以将常量变量放入某个特殊部分,您可以放入FLASH/ROM,通常使用自定义链接器脚本/编译器开关

  • 与任何其他值一样,它将在程序运行期间存在于RAM中,也可能存在于可执行文件中。您的意思是“#定义一个宏”吗?请记住,这个决定不仅仅是使用哪种资源……类型检查,遵循范围规则。有关更多讨论,请参阅。对不起,哪个“可能”?我把“可能”改为“应该”,因为“可能”是错误的。