您的位置:首页 > 其它

链接属性与存储类型

2016-02-23 11:55 141 查看

1. 链接属性

各个源文件被编译后,所有的目标文件+从函数库中引用的函数(一般是归档库文件,*.a类型)经过链接器链接,形成一定格式的可执行程序,如elf格式。如果相同的标示符出现在几个不同的源文件中,他们是否表示同一个实体。这由标示符的链接属(linkage)决定。

链接属性有三种:外部(external),内部(internal),无(none)

外部属性的标示符在整个程序内,不论出现于哪个文件,不论声明多少次,都指的同一个实体。即每个翻译单元都可以访问这个东西(前提是编译器知道有这个东西存在,如在不同的翻译单元添加extern关键字),普通的函数、变量、模版和命名空间都有外链接。

内部属性,只在同一个源文件的所有声明中指同一个实体。即在某个翻译单元里定义的东西只能在翻译单元里使用。在任何函数以外定义的静态变量都有内链接属性。

无属性,该标示符的多个声明都被当做独立的个体。在函数里定义的变量只存在于该函数内部,没有任何链接,即none。

这里有两个关键字:extern 和 static,用于在声明中修改标示符的链接属性。

如果某个声明默认情况下具有外部external属性,加上static后,可以将其链接属性变为internal。

static可以将该标示符的作用域限定为本文件,防止被其他源文件使用。

注:static只对缺省链接属性为external的声明才有改变链接属性的效果。

关键字extern的使用:(引用cameracanon的专栏

在源文件A里定义的函数,在其它源文件里是看不见的(即不能访问)。为了在源文件B里能调用这个函数,应该在B的头部加上一个外部声明:

extern   函数原型;


这样,在源文件B里也可以调用那个函数了。

注意这里的用词区别:在A里是定义,在B里是声明。一个函数只能(也必须)在一个源文件里被定义,但是可以在其它多个源文件里被声明。定义引起存储分配,是真正产生那个实体。而声明并不引起存储分配。打一个粗俗的比方:在源文件B里声明后,好比在B里开了一扇窗,让它可以看到A里的那个函数。

//《C++ Primer》 P50
//全局变量具有外部链接属性
//file1.cc
int counter;  //define
//file2.cc
extern int counter;   //uses counter from file1
++counter;    //increments counter defined in file1


//又如(《C++ Primer》 P50例子)
//const变量具有内部链接属性,默认值存在于定义的文件中,不能被其它文件访问
//file_1.cc
//defines and initializes a const that is accessible to other files
extern const int bufSize = fcn();   //用extern修改const变量的链接属性

//file_2.cc
extern const int bufSize;  //uses bufSize from file_1
for(int index=0;index!=bufSize;++index);    //uses bufSize defined int file_1
//...


如果定义函数的c/cpp文件在对应的头文件中声明了定义的函数,那么在其他c/cpp文件中要使用这些函数,只需要包含这个头文件即可。

如果你不想包含头文件,那么在c/cpp中声明该函数。一般来说,声明定义在本文件的函数不用“extern”,声明定义在其他文件中的函数用“extern”,这样在本文件中调用别的文件定义的函数就不用包含头文件

extern用在变量声明时,相当于把另一个“翻译单元”里的某个变量声明为本“翻译单元”里的一个同名全局变量。编译器不会为extern变量分配内存,因为在其它地方已经为它分配过内存。



2. 存储类型

变量的存储类型(storage class)是指存储变量值的内存类型。变量的存储类型决定了变量何时创建,何时销毁以及它的值保持多久。

有三个地方可以用于存储变量:普通内存,运行时堆栈,硬件寄存器。

变量的存储类型取决与它的声明位置。(引用点滴成行–学习博客

(1)在任何代码块之外声明的变量总是存储于静态内存(在以前的C语言中,该内存快分为程序的数据段+bss段,BSS(Block Started by Symbol)通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。 注意和数据段的区别,BSS存放的是未初始化的全局变量和静态变量,数据段存放的是初始化后的全局变量和静态变量;但在C++中,没有这个区分,他们共同占用同一块内存区),而不是堆栈中,这类变量是静态变量(或全局变量)。

静态变量在程序运行之前创建,在程序的整个执行过程中都存在。

(2)在代码块内声明的变量默认是自动变量(automatic),存储于堆栈中,这类变量叫做自动(auto)变量。在程序执行到该代码块时,内部的自动变量才被创建,当程序离开该代码块时,自动变量销毁。

在代码块内部的变量如果给它加上static关键字,可以使其变为静态变量。

注:

1.修改变量的存储类型,不等于修改变量的作用域,它仍然只能在该代码块内部按名字访问。

2.函数的形式参数不能声明为静态,因为函数的参数传递是通过堆栈进行的,用于支持递归。

(3)在变量前加上register关键字,可以告诉编译器该变量应该存储于机器的硬件寄存器,而不是内存。如果有很多register变量,编译器只会选几个实际存储于寄存器。

不同存储类型变量的初始化问题:

静态变量总是默认初始化为0,除非显式的赋值。

自动变量没有初始值,或认为它的值是个垃圾,所以在声明一个自动变量时最好在使用前进行赋初值。

- static关键字总结

1.当它用于函数定义时,或用于代码块之外的变量声明时,static关键字用于修改标识符的链接属性,从external改为internal,但标识符的存储类型和作用域不受影响。用这种方式声明的函数或者变量只能在声明它们的源文件中访问。

2.当它用于代码块内部的变量声明时,static关键字用于修改变量的存储类型,从自动变量改为静态变量,但变量的链接属性和作用域不受影响。用这种方式声明的变量在程序执行之前创建,并在程序的整个执行期间一直存在。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: