位置:学校首页 > 学校动态>苏州有没有靠谱的C语言培训班
c变量有三种链接属性:
外部链接,extern修饰的,或者没有static修饰的具有文件作用域的变量具有外部链接属性
内部链接,static修饰的具有文件作用域的变量具有内部链接属性
无链接,块作用域,函数作用域和函数原型作用域的变量无链接属性
再稍作解释,没有static修饰,且具有文件作用域的变量,他们在链接时,多个同名标识符的变量较终都绑定到同一个实体。而static修饰的具有文件作用域的变量就不一样了,不同文件内,即便标识符名字相同,它们也绑定到了不同的实体。
因此,如果我们希望某个变量或函数只在某一个文件使用,那么使用static修饰是一个很好的做法。
同样的,来看一个例子。
#include
int a = 5; //文件作用域,外部链接属性,其他文件可通过extern int a的方式使用该文件的a
static b = 6; //文件作用域,内部链接属性,即便其他文件也有同名标识符,它们也是不同的
int main(void)
{
int sum = 0 ; //无链接属性
sum = a + b;
printf("sum is %d
",sum);
return 0;
}
从代码中可以看到,a和b都具有文件作用域,a具有外部链接属性,而b具有内部链接属性,sum具有块作用域,因此无链接属性。
存储期
实际上作用域和链接属性都描述了标识符的可见性,而存储期则描述了这些标识符对应的对象的生存期。存储期,也分下面几种:
静态存储期,程序执行期间一直都在,文件作用域的变量具有静态存储期
自动存储期,它(变长数组除外)从块开始,到块末尾,因此,块作用域的变量具有自动存储期,它在栈中存储,需要显式初始化。
动态分配存储期,即通过malloc分配内存的变量。它在堆中存储,需要显式初始。
线程存储期,从名字可以知道, 它与线程相关,使用关键字_Thread_local声明的变量具有线程存储期,它从声明到线程结束一直存在。
关于初始化,可参考《C语言入坑指南-被遗忘的初始化》。
同样地,我们通过下面的代码来更好地理解存储期:
#include
int num1 = 222; //静态存储期
static int num2 = 111; //静态存储期
int add(int a,int b)
{
static int tempSum = 0; //静态存储期
tempSum = tempSum + a + b;
return tempSum;
}
int main(void)
{
printf("num1=%d,num2=%d
",num1,num2);
int sum = 0; //自动存储期
sum = add(num1,num2);
printf("first time sum=%d
",sum);//sum = 333
sum = add(num1,num2);
printf("second time sum=%d
",sum); //sum = 666
return 0;
}
另外,如果我们通过nm命令查看编译出来的程序文件的符号表,我们可以找到num1,num2,tempSum,而没有sum,前者所用的内存数量在编译时就确定了。关于nm命令的使用可以参考《linux常用命令-开发调试篇》。
$ gcc -g -o lifetime lifetime.c
$ nm lifetime|grep num1
0000000000601038 D num1
$ nm lifetime|grep num2
000000000060103c d num2
$ nm lifetime|grep tempSum
0000000000601044 b tempSum.2289
$ nm lifetime|grep sum
$