C语言中auto,static,register,extern存储类型的用法

发布时间:2018-06-30 14:56:42   来源:文档文库   
字号:

C语言中提供存储类型说明符autoexternstaticregister,说明的四种存储类别。四种存储类别说明符有两种存储期:自动存储期和静态存储期。其中autoregister对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块是被建立,它在该程序块活动时存在,退出该程序块时撤销。

Auto

在函数内部定义的变量成为局部变量。局部变量称为自动变量,这就与使用可选关键字a u t o定义局部变量这一作法保持一致。局部变量仅由其被定义的模块内部的语句所访问。换言之,局部变量在自己的代码模块之外是不可知的。切记:模块以左花括号开始,以右花括号结束。
对于局部变量,要了解的最重要的东西是:它们仅存在于被定义的当前执行代码块中,即局部变量在进入模块时生成,在退出模块时消亡。
定义局部变量的最常见的代码块是函数。

请见以下代码:

#include "stdio.h"
main()
{

int i,num;
num=2;
for (i=0;i<3;i++)
{ printf("The num equal %d \n",num);
num++;
{
auto int num=1;
printf("The internal block num equal %d \n",num);
num++;
}
}
}

运行的结果为:


其实现在都不用打auto 编译器默认为auto
不信可以把auto删除试试

Static

C语言中,存储类型static字面意思很容易把我们导入歧途,其实它的作用有三条

1,隐藏。这也是最重要的一条。

2static的第二个作用是保持变量内容的持久。

3,第三个作用是默认初始化为0

1)这里就先说第一条,当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。我举例来说明。我们要同时编译两个源文件,一个是my.c,另一个是main.c 下面是my.c的内容

char a = 'm'; // m为全局变量

void myage()

{

printf("my age is 25 \n");

}

下面是main.c

int main(void)

{

extern char m; //外部属性的变量使用前一定要先声明

printf("%c ", m);

(void)myage();

return 0;

}

运行的结果是:m my age is 25

为什么在my.c中定义的全局变量m和函数myage能在main.c中使用?前面说过,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。此例中,m是全局变量,myage是函数,并且都没有加static前缀,因此对于另外的源文件main.c是可见的。

如果加了static,就会对其它源文件隐藏。例如在mmyage的定义前加上staticmain.c就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。Static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏,而对于变量,static还有下面的作用。

2)保持变量内容的持久性。

存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底static还是用来隐藏的。这种用法也比较常见,如下面的例子:

#include "stdio.h"

main()

{

int i,num;

num=2;

for(i=0;i<3;i++)

{

printf(" The num equal %d \n",num);

num++;

{

static int num=1;

printf("\40:The internal block num equal %d\n",num);

num++;

}

}

}

运行的结果:

(3)默认初始化为0

其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵,我们可以一个一个地把所有元素都置0,然后把不是0的几个元素赋值。如果定义成静态的,就省去了一开始置0的操作。再比如要把一个字符数组当字符串来用,但又觉得每次在字符数组末尾加’\0’太麻烦。如果把字符串定义成静态的,就省去了这个麻烦,因为那里本来就是’\0’。不妨做个小实验验证一下:

#include

int a;

int main(void)

{ int i;

static char str[10];

printf("integer: %d; string: (begin)%s(end)", a, str);

return 0;

}

程序的运行结果如下

integer: 0; string: (begin)(end)

最后对static的三条作用做一句话总结。首先static的最主要功能是隐藏,其次因为static变量存放在静态存储区,所以它具备持久性和默认值0

部分来源于:

extern

C语言中,修饰符extern用在变量或者函数的声明前,用来说明此变量/函数是在别处定义的,要在此处引用

1. extern修饰变量的声明。举例来说,如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。这里需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说a.c要引用到v,不只是取决于在a.c中声明extern int v,还取决于变量v本身是能够被引用到的。这涉及到c语言的另外一个话题--变量的作用域。能够被其他模块以extern修饰符引用到的变量通常是全局变量。还有很重要的一点是,extern int v可以放在a.c中的任何地方,比如你可以在a.c中的函数fun定义的开头处声明extern int v,然后就可以引用到变量v了,只不过这样只能在函数fun作用域中引用v罢了,这还是变量作用域的问题。对于这一点来说,很多人使用的时候都心存顾虑。好像extern声明只能用于文件作用域似的。

2. extern修饰函数声明。从本质上来讲,变量和函数没有区别。函数名是指向函数二进制块开头处的指针。如果文件a.c需要引用b.c中的函数,比如在b.c中原型是int fun(int mu),那么就可以在a.c中声明extern int funint mu),然后就能使用fun来做任何事情。就像变量的声明一样,extern int funint mu)可以放在a.c中任何地方,而不一定非要放在a.c的文件作用域的范围中。对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文件。使用extern和包含头文件来引用函数有什么区别呢?extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。这大概是KISS原则的一种体现吧!这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。在大型C程序编译过程中,这种差异是非常明显的。

3. 此外,extern修饰符可用于指示C或者C++函数的调用规范。比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同。

(来源:

请思考下面的例子:

#include "stdio.h"
int a,b,c;
void add()
{ int a;
a=3;
c=a+b;
}
void main()
{ a=b=4;
add();
printf("The value of c is equal to %d\n",c);
}

运行的结果:c=7

Register

C语言中,register表示请求编译器把这个数据存储在寄存器中。寄存器是CPU里面的一块能够快速访问的地方,比内存还快。通过register,编译器能知道这个变量需要很快的速度,并对它进行优化。不过,register只是请求编译器把数据存储到寄存器中,并不能保证这个数据一定在寄存器中,由于某些原因(比如寄存器不够用或编译器认为没必要)可能不会被存储到寄存器中。另外,寄存器没有地址,所以对register变量取地址是不会编译通过的,即使编译器没有把它存到寄存器中。

另外register 只是寄存器变量,表示这个数据要保存在寄存器中,和任何运算都没有关系,比如你的变量是保存在内存还是缓存中都不重要,和程序没有多大联系,你把register去掉,程序该怎么样就怎么样,用寄存器变量是为了提高程序运行速度,因为寄存器是取值和修改最快的,所以把那些需要多次使用的变量保存在寄存器中是一种提高效率的做法,和算法没关

请思考以下的程序:

void main()
{
register int i;
int tmp=0;
for(i=1;i<=100;i++)
tmp+=i;
printf("The sum is %d\n",tmp);
}

再对比以下的程序:

void main()
{
int i;
int tmp=0;
for(i=1;i<=100;i++)
tmp+=i;
printf("The sum is %d\n",tmp);
}

通过改变i的取值范围观察运行的时间长短。

本文来源:https://www.2haoxitong.net/k/doc/e090c7741a37f111f0855bcf.html

《C语言中auto,static,register,extern存储类型的用法.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式