全局变量都是静态变量,局部变量都是动态变量,静态局部变量和全局变量的区别是什么?
来源:微信官方账号【编程明珠】
作者:手表老师
这些是编程语言中的基本概念。如果你不清楚题目,不知道
作用域,链接属性,存储期
等概念的具体含义,那么你就不要错过这篇文章。为了更清楚地理解我们的问题,我们需要知道三个概念:范围、链接属性和存储周期。在C语言中,作用域用于描述标识符可以访问的区域。
常见范围如下:
为了便于说明,我们来看一个例子,这个例子很容易理解:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *作者:守望老师来源:微信官方账号编程朱基的个人博客:3359 www.yanbinghu.com * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//定位在函数之外,文件作用域为staticintnum2=111//在函数外定义,文件作用域intswap(int*a,int * b);//这里a,b是函数原型作用域intswap (int * a,int * b){ if(null==a null==b)goto error;else { int temp=* a;//在函数中定义,块作用域* a=* b;* b=温度;return0}//printf(tempis%dn ,temp);//因为temp有block作用域,所以在这里不能直接使用error://goto语句的标签,可以参考之前的{ printf( inputparaisNULL n );return-1;} } int main(void){ printf( num1=% d,num2=%dn ,num 1,num 2);swap(num1,num 2);//num1num2有文件作用域,可以直接在main函数中使用printf (Num1=% d,Num2=% d ,Num1,num 2);return0}
# includestdio.h
intnum1=222//位于函数之外,具有文件范围
staticintnum2=111//在函数外部定义,具有文件范围
intswap(int*a,int * b);//这里A和B是函数原型的作用域
intswap(int*a,int*b)
{
if(NULL==aNULL==b)
gotoerror
其他
{
int temp=* a;//在函数、块范围内定义
* a=* b;
* b=温度;
return0
}
//printf(tempis%dn ,temp);//此处不能直接使用temp,因为它有块范围。
错误:goto语句的标签,函数的作用域,所以之前可以引用。
{
printf( inputparaisNULL n );
return-1;
}
}
intmain(void)
{
printf(num1=%d,num2=%dn ,num1,num 2);
swap(num1,num 2);//num1num2有文件作用域,可以直接在main函数中使用。
printf(num1=%d,num2=%d ,num1,num 2);
return0
}大家可以看到,error标签有一个函数作用域,在整个函数中都是可见的,而temp标签有一个block作用域,所以不能直接用在花括号外面。而num1和num2有文件作用域,所以main函数可以直接使用。
属性是《hello程序是如何变成可执行文件的》。我们谈到了编译过程,最后一步是链接。
链接属性决定了在不同作用域的同名标识符能否绑定到同一个对象或者函数
。或者,编译后不同作用域的标识符是否是同一个实体。c变量有三个关联属性:
再解释一下,没有静态修改的有文件作用域的变量,当它们被链接的时候,同一个标识符的多个变量最终被绑定到同一个实体。但是,静态修改文件范围的变量是不同的。在不同的文件中,即使标识符名称相同,它们也绑定到不同的实体。
因此,如果我们希望某个变量或函数只在某个文件中使用,那么使用静态装饰是一个很好的做法。
同样,我们来看一个例子。
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *作者:守望老师来源:微信官方账号编程朱基的个人博客:3359 www.yanbinghu.com * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//文件作用域,外部链接属性,其他文件可以通过externinta的方式使用本文件的astaticb=6; //文件作用域,内部链接属性,即使其他文件有相同的标识符,也是不同的int main(void){ int sum=0;//无链接属性sum=a b;printf(sumis%dn ,sum);return0}
# includestdio.h
inta=5;//文件作用域,外部链接属性,其他文件可以以externinta的方式使用该文件的
static b=6;//文件作用域,内部链接属性,即使其他文件有相同的标识符,也是不同的。
intmain(void)
{
int sum=0;//没有链接属性
sum=a b;
printf(sumis%dn ,sum);
return0
}从代码中可以看出,A和B都有文件作用域,A有外部链接属性,B有内部链接属性,sum有块作用域,所以没有链接属性。
实际上,存储期间的范围和链接属性描述了标识符的可见性,而存储期间描述了这些标识符对应的对象的生存期。储存期也分为以下几种类型:
请参考《C语言入坑指南-被遗忘的初始化》进行初始化。
同样,我们可以通过下面的代码更好地理解存储周期:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *作者:守望老师来源:微信官方账号编程朱基的个人博客:3359 www.yanbinghu.com * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *静态存储周期staticintnum2=111//静态存储周期intad (inta,intb){ static inttempum=0;//静态存储周期tempSum=tempSum a b;returntempSum}intmain(void){printf(num1=%d,num2=%dn ,num1,num 2);int sum=0;//自动存储周期总和=add(num1,num 2);printf(firsttimesum=%dn ,sum);//sum=333sum=add(num1,num 2);printf(secondtimesum=%dn ,sum);//sum=666 return 0;}
# includestdio.h
intnum1=222//静态存储周期
staticintnum2=111//静态存储周期
intadd(inta,intb)
{
staticinttempSum=0;//静态存储周期
tempSum=tempSum a b;
returntempSum
}
intmain(void)
{
printf(num1=%d,num2=%dn ,num1,num 2);
int sum=0;//自动存储期
sum=add(num1,num 2);
printf(firsttimesum=%dn ,sum);//sum=333
sum=add(num1,num 2);
printf(secondtimesum=%dn ,sum);//sum=666
return0
}另外,如果我们通过nm命令查看编译后的程序文件的符号表,可以发现没有Sum的num1,num2,tempSum。前者使用的内存量是在编译时确定的。关于nm命令的使用,请参考《linux常用命令-开发调试篇》。
$ gcc-g-olifetimelifetime . c $ nmlifetime grep num 100000000000601038 dnum 1 $ nmlifetime grep num 200000000060103 cdnum 2 $ nmlifetime greptempsum 0000000000601044 btempsum . 2289 $ nmlifetime grep sum $ grep num 1
0000000000601038Dnum1
$nmlifetimegrepnum2
000000000060103cdnum2
$nmlifetimegreptempSum
0000000000601044btempSum
$nmlifetimegrepsum
$
什么全局变量,局部变量,静态局部变量,静态全局变量在这里,我们很容易区分以上变量类型。实际上,这只是另一种说法:
全局:具有文件范围的变量。
静态:具有静态存储周期或内部链接属性。
局部:具有函数或块范围的变量。
所以结合起来就好理解了。
当然这只是为了区分他们,并不是他们严格的定义。更好的方法是通过代码来理解它:
# includesdio . hint num 1=222;//全局变量staticintnum2=111//静态全局变量intad (inta,intb){ static inttempum=0;//静态局部变量tempSum=tempSum a b;returntempSum}intmain(void){printf(num1=%d,num2=%dn ,num1,num 2);int sum=0;//局部变量sum=add(num1,num 2);printf(firsttimesum=%dn ,sum);//sum=333 return 0;}
intnum1=222//全局变量
staticintnum2=111//静态全局变量
intadd(inta,intb)
{
staticinttempSum=0;//静态局部变量
tempSum=tempSum a b;
returntempSum
}
intmain(void)
{
printf(num1=%d,num2=%dn ,num1,num 2);
int sum=0;//局部变量
sum=add(num1,num 2);
printf(firsttimesum=%dn ,sum);//sum=333
return0
}
本文摘要如下:
参考https://en.wikipedia.org/wiki/Global_variables
https://en.wikipedia.org/wiki/Local_variable
《C11标准文档》
关注微信官方账号【编程明珠】,获取更多Linux/C/C/Python/Go/algorithms/tools等原创技术文章。后台免费获取经典电子书和视频资源。