C语言中变量的位置与程序优化
前几天一个朋友在网上问我:“怎么区分全局变量,静态变量和自动变量?”我觉得奇怪,他怎么问一个初学者的问题,我这位朋友其实编程挺厉害的,呵呵。接着他说是:“计算机怎么区分”。确实,人区分各种变量一看就知道了,但是计算机怎么区分呢?没有编译知识可能一下子也难弄懂。
计算机理解力是没法和我们相比的,但是它比我们快。我们可以把这些变量分开来放,从不同地方取来的就是不同的变量。告诉计算机去找的就是符号表。当然,生成符号表是编译器的事,我们不用管。但是了解一点总是有好处的。这里我以Unix ELF(Executalbe and Linkable Format)格式文件为例说明编译器是怎么安排全局变量,静态变量和自动变量的位置的。
ELF可重定位目标文件包括:ELF头以及.text,.rodata, .data ,.bss ,.symtab, .rel.text, .rel.data 等节。
1、全局变量:已初始化的保存在.data段中 ,未初始化的表示为.bss段的一个占位符;
2、静态变量:根据是否初始化分别在.data 和.bss段中分配空间;
3、自动变量(非静态局部变量):在运行时保存在栈中。既不在.data 段中也不在.bss段中。
其实我们可以编写一个简单的程序,编译了以后用objdump命令查看各种变量所在的节。
知道了各种变量在运行时的位置也就知道了他们的储存期,而且了解变量的位置对编写高性能程序也非常有帮助。
我们知道嵌入式对程序的性能要求是非常高的,函数的参数列表越长那么函数调用的开销就越大,这个时候我们可以使用全局变量提高程序的性能。将函数和变量声明为static可防止函数和变量被其它模块不正确的使用。
关于自动变量,请看下面的两个程序:
long product;
void factorialA(long n)
{
long i;
for(i = 1; i <= n;i++ ){
product *= i;
}
void factorialB(long n)
{
long i;
long x = 1;
for(i = 1; i <= n;i++ ){
x *= i;
}
product = x;
}
在n值较大的时候,上面两个程序的性能是有显著差别的。 这是利用了程序的局部性原理。
计算机理解力是没法和我们相比的,但是它比我们快。我们可以把这些变量分开来放,从不同地方取来的就是不同的变量。告诉计算机去找的就是符号表。当然,生成符号表是编译器的事,我们不用管。但是了解一点总是有好处的。这里我以Unix ELF(Executalbe and Linkable Format)格式文件为例说明编译器是怎么安排全局变量,静态变量和自动变量的位置的。
ELF可重定位目标文件包括:ELF头以及.text,.rodata, .data ,.bss ,.symtab, .rel.text, .rel.data 等节。
1、全局变量:已初始化的保存在.data段中 ,未初始化的表示为.bss段的一个占位符;
2、静态变量:根据是否初始化分别在.data 和.bss段中分配空间;
3、自动变量(非静态局部变量):在运行时保存在栈中。既不在.data 段中也不在.bss段中。
其实我们可以编写一个简单的程序,编译了以后用objdump命令查看各种变量所在的节。
知道了各种变量在运行时的位置也就知道了他们的储存期,而且了解变量的位置对编写高性能程序也非常有帮助。
我们知道嵌入式对程序的性能要求是非常高的,函数的参数列表越长那么函数调用的开销就越大,这个时候我们可以使用全局变量提高程序的性能。将函数和变量声明为static可防止函数和变量被其它模块不正确的使用。
关于自动变量,请看下面的两个程序:
long product;
void factorialA(long n)
{
long i;
for(i = 1; i <= n;i++ ){
product *= i;
}
void factorialB(long n)
{
long i;
long x = 1;
for(i = 1; i <= n;i++ ){
x *= i;
}
product = x;
}
在n值较大的时候,上面两个程序的性能是有显著差别的。 这是利用了程序的局部性原理。