2016-05-13 66 views
-3

我知道,在C宏如:嵌入式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(代码)中。

如果我错了,请问我是否正确?

+3

宏不会影响运行时,它们会在编译之前影响代码。 –

+0

请每个问题一个问题。 –

+1

除非使用,否则VARNULL不存储在任何地方。如果使用'VARNULL',编译器就会看到代码,就好像你写了'(u8)0'一样,它会适当地使用该零。使用'CALL_FUNCS',如果你不使用它,则没有任何东西进入程序。如果你调用它,那么在代码中的那个地方会产生三个函数调用,就像你长时间写的那样。如果你有一个可调试的图像(可能你不在嵌入式系统中),那么一个'const'变量会出现在符号表中,并且可以使调试更容易;宏没有被记录,所以调试起来更困难。 –

回答

1

宏在预处理器进行C编译之前会先处理宏和任何其他以#为前缀的指令;他们不会生成任何代码,而是生成源代码,然后由编译器进行处理,就像直接在代码中键入一样。因此,在您的示例代码:

int main() 
{ 
    CALL_FUNCS(2) ; 
} 

结果在下面的生成源代码

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

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

关于常量和#define,文字常量宏也是文本替换,并将作为文字常量放置在代码中。 A const另一方面是变量。编译器可以简单地在C++中插入一个文字常量,该常量生成的代码从内存中获取该常量的代码量较少,并且C++编译器不会以相同的方式运行。但是,因为它是一个变量,所以可以将其作为地址 - 如果您的代码的地址为const,则const必须具有存储空间。无论存储在RAM还是ROM,取决于您的编译器和链接器配置 - 您应该查阅工具链文档以了解它如何处理常量存储。

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

4

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

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