【问题标题】:How macros in embedded C affect memory?嵌入式 C 中的宏如何影响内存?
【发布时间】:2016-05-13 14:46:43
【问题描述】:

我知道 C 中的宏,例如:

#define VARNULL (u8)0

不会将此VARNULL 存储在 RAM 中,但这当然会增加 FLASH 中的代码大小。

但是如果我有一个多行宏,例如:

#define CALL_FUNCS(x) \
do { \
  func1(x); \
  func2(x); \
  func3(x); \
} while (0)

知道func1func2func3 是来自不同.c 文件的函数。这是否意味着这些函数将存储在 RAM 中?当然还有 FLASH(代码)。

如果我错了,请纠正我?

【问题讨论】:

  • 宏不影响运行时,它们会影响编译前的代码。
  • 每个问题一个问题。
  • 除非使用它,否则VARNULL 不会存储在任何地方。如果你使用VARNULL,编译器看到的代码就像你写了(u8)0,它会适当地使用那个零。使用CALL_FUNCS,如果您不使用它,则不会进入程序。如果您调用它,则在代码中的该位置依次生成三个函数调用,就像您将它们写出来一样。如果你有一个可调试的镜像(可能你在嵌入式系统中没有),那么符号表中就会出现一个const 变量,可以使调试更容易;没有记录宏,因此更难调试。
  • 请参阅static const vs #define vs enum 了解有关常量和宏的讨论。
  • 没有“嵌入式C”语言。

标签: c embedded microcontroller


【解决方案1】:

您一直说“当然”宏会“存储”在目标设备的闪存中,但事实并非如此。

宏存在于源代码中;它们在编译期间被它们定义的值替换。闪存中的程序不会以任何有意义的方式“包含”它们。

【讨论】:

    【解决方案2】:

    宏和任何其他前缀为# 的指令在C 编译之前由预处理器处理;它们不生成任何代码,而是生成源代码,然后由编译器处理,就像您直接输入代码一样。所以在你的例子中,代码:

    int main()
    {
        CALL_FUNCS(2) ;
    }
    

    生成以下源代码

    int main()
    {
        do { \
          func1(2);
          func2(2);
          func3(2);
        } while (0) ;
    }
    

    就这么简单。如果您从不调用宏,它将完全不生成任何代码。如果您多次调用它,它将多次生成代码。宏没有什么聪明的地方只是在编译之前生成的文本替换;编译器对此做什么完全取决于宏扩展为什么,而不是它是一个宏这一事实 - 编译器只看到生成的代码,而不是宏定义。

    相对于 const 与 #define,文字常量宏也是一种文字替换,并将作为文字常量放置在代码中。另一方面,const 是一个变量。编译器可以简单地插入一个文字常量,该常量会生成更少的代码来从内存中获取常量,在 C++ 中,这保证了简单类型,并且 C 编译器的行为方式不同是不寻常的。但是,因为它是一个变量,所以您可以使用它的地址 - 如果您的代码确实使用了const 的地址,那么const 必然有存储空间。该存储是在 RAM 中还是在 ROM 中取决于您的编译器和链接器配置 - 您应该查阅工具链文档以了解它如何处理 const 存储。

    使用const 的一个好处是与宏不同,const 变量具有强类型和范围。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-30
      • 1970-01-01
      • 1970-01-01
      • 2013-08-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多