随笔 - 56, 文章 - 0, 评论 - 0, 引用 - 0
数据加载中……

存储类、链接和内存管理

1、一个具有外部链接的变量可以在一个多文件程序的任何地方使用。一个具有内部链接的变量可以在一个文件的任何地方使用。
如:
int giants=5;  //文件作用域,外部链接
static int dodgers=3;  //文件作用域,内部链接
int main()
{
    ......
}

和该文件属于同一程序的其他文件可以使用变量giants,变量dodgers是该文件私有的,但是可以被该文件中的任一函数使用。

2、存储时期
一个C变量有以下两种存储时期之一:静态存储时期和自动存储时期。如果一个变量具有静态存储时期,它在程序执行期间将
一直存在。具有文件作用域的变量具有静态存储时期。注意对于具有文件作用域的变量,关键词static表明链接类型,并非
存储时期。一个使用static声明了的文件作用域变量具有内部链接,而所有的文件作用域变量,无论它具有内部链接,还是
具有外部链接,都具有静态存储时期。
具有代码块作用域的变量一般情况下具有自动存储时期,在程序进入定义这些变量的代码块时,将为这些变量分配内存;当
退出这个代码块时,分配的内存将被释放。

      5个存储类
 存储类                           时期     作用域     链接     声明方式
 自动                              自动     代码块     空         代码块内
 寄存器                           自动     代码块     空         代码块内,使用关键字register
 具有外部链接的静态            静态     文件       外部     所有函数之外
 具有内部链接的静态            静态     文件       内部     所有函数之外,使用关键字static
 空链接的静态                   静态     代码块     空         代码块内,使用关键字static
 
如果在内层代码块定义了一个具有和外层代码块变量同一名的变量,那么在内层代码块定义的名字是内层代码块内使用的变量,
我们称之为内层定义覆盖了外部定义,但当运行离开内层代码块时,外部变量重新恢复作用。
如:

#include<stdio.h>
int main()
{
    
int x=30;
    printf(
"x in outer block :%d\n",x);
    
{
        
int x=77;
        printf(
"x in inner block :%d\n",x);
    }

    printf(
"x in outer block :%d\n",x);
    
while(x++<33)
    
{
        
int x=100;
        x
++;
        printf(
"x in while loop :%d\n",x);
    }

    printf(
"x in outer block :%d\n",x);

    
return 0;
}
显示结果为:
in outer block :30
in inner block :77
in outer block :30
in while loop :101
in while loop :101
in while loop :101
in outer block :34

”静态“是指变量的位置固定不动。具有文件作用域的变量自动具有静态存储时期。也可以创建具有代码块作用域,兼具静态存储
的局部变量。这些变量和自动变量具有相同的作用域,但当包含这些变量的函数完成工作时,它们并不小时。也就是说,这些
变量具有代码块作用域、空链接,却有静态存储时期。从一次函数调用到下一次调用,计算机都记录它们的值。如:
#include<stdio.h>
void trystat(void);
int main()
{
    
int count;

    
for(count=1;count<=3;count++)
    
{
        printf(
"Here comes iteration %d:\n",count);
        trystat();
    }


    
return 0;
}

void trystat(void)
{
    
int fade=1;
    
static int stay=1;

    printf(
"fade=%d and stay=%d\n",fade++,stay++);
}
显示结果为:
Here comes iteration 1:
fade
=1 and stay=1
Here comes iteration 
2:
fade
=1 and stay=2
Here comes iteration 
3:
fade
=1 and stay=3
补充:
静态变量stay的值被加1,而变量fade每次都重新开始,表明初始化的不同:在每次调用trystat()时fade都被初始化,而stay
只在编译trystat()时被初始化一次。如果不显式地对静态变量进行初始化,它们将被初始化为0.
int fade=1;
static int stay=1;
第一个语句却是是函数trystat()的一部分,每次调用该函数时都会执行它。它是个运行时的动作。而第二个语句实际上并不是
函数trystat()的一部分。如果用调试程序逐步执行该程序,您会发现程序看起来跳过了那一步。那是因为经他i变量和外部变量
在程序调入内存时就已经就位了。把这个语句放在trystat()函数中是为了告诉编译器只有函数trystat()可以看到该变量。
对函数参量不能使用static
int wontwork(static flu);  //不允许

int Hocus;
int magic();
int main()
{
    
int Hocus;    //声明Hocus,默认为自动变量
    
}

int Pocus;
int magic()
{
    auto 
int Hocus;    //把局部变量Hocus显式第声明为自动变量
    
}

上面代码中,创建了4个独立的变量,main()中的Hocus默认为自动变量,而且是main()的局部变量,magic()中的Hocus被显式第
声明为自动变量,只对magic()可见。外部变量Hocus对main()或magic()不可见,但对文件中其他不单独用于局部Hocus的函数都
可见。最后,Pocus是一个外部变量,对magic()可见而对main()不可见,因为Pocus的声明在main()之后。

3、外部变量初始化
不同与自动变量的是,如果您不对外部变量进行初始化,它们将自动被赋初值0,这一原则也使用于外部定义的数组元素。不同于
自动变量,只可以用常量表达式来初始化文件作用域变量:

int x=10;    //可以
int y=3+20;    //可以
size_t z=sizeof(int);    //可以
int x2=2*x;    //不可以,x为变量

4、定义和声明
int tern=1;
main()
{
    external 
int tern;
}
这里,tern声明了两次。第一次声明为变量留出了存储空间。它构成了变量的定义。第二次声明只是告诉编译器要使用先前定义
的变量tern,因此不是一个定义。第一次声明称为定义声明,第二次声明称为引用声明。关键字extern表明该声明不是一个定义
,因为它只是编译器参考其他地方。
如果这样做:
extern int tern;
int main()
{
}
那么编译器规定tern的真正定义是在其他地方或文件中。这样的声明不会引起空间分配。因此不要用extern来进行外部定义;
只用来引用一个已经存在的外部定义。
一个外部变量只可以进行一次初始化,而且一定是在变量被定义时进行。下面的语句是错的:
extern char permis='Y';

因为关键字extern的存在标志着这是一个引用声明,而非定义声明。

5、存储类说明符
5个:auto、register、static、extern以及typedef。
自动变量具有代码块作用域、空链接和自动存储时期。它们是局部的,为定义它们的代码块(通常为一个函数)所私有。寄存器
变量与自动变量具有相同属性,但编译器可能使用速度更快的内存或寄存器来存储它们。无法获取一个寄存器变量的地址。
具有静态存储时期的变量可能具有外部链接、内部链接或空链接。当变量在文件的所有函数之外声明,它是一个具有文件作用域
的外部变量,具有外部链接和静态存储时期。如果在这样的声明中再加上关键字static,将获得一个具有静态存储时期、文件
作用域和内部链接的变量。如果在一个函数内使用关键字static声明变量,变量将具有静态存储时期、代码块作用域和空链接。

posted on 2011-03-13 10:02 八路 阅读(213) 评论(0)  编辑 收藏 引用 所属分类: C primer 易错点


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理