存储类别、链接、和内存管理(一)

涉及内容:

关键字:auto、extern、static、register、const、volatile、restricted(受限制的 保密的)、_Thread_local、_Atomic
函数:rand()、srand()、time()、malloc()、calloc()、free()
如何确定变量的作用域(可见范围)和声明周期(它存在多长时间)

***** ********* ************************ ** * 好好理解"对象"这个概念。************************************************

一、存储类别

1.1.从硬件方面来看,被存储的每个值都占一定的物理内存。C语言把这一块内存称为对象。对象可以存储一个或多个值。一个对象可能并未存储到实际的值,但是它在存储适当的值时一定具有相应的大小。
1.2.从软件方面来看,程序需要一种方法访问对象,可以通过声明变量来完成。

int	entity = 2;//这条语句创建了一个名为entity的标识符。
//上边这条语句,标识符entity是软件(C程序)指定硬件内存中的对象的方式。该声明还提供了存储在对象中的值。

标识符是一个名称,在这种情况下,标识符可以用来指定特定对象的内容(也就是指定特定内存上的内容)。

1.3.变量名不是指定对象的唯一途径。

int * pt = &entity;  //这一行声明中,pt是一个标识符,它指定了一个存储地址的标识符。
int rank[10];

但是,*pt不是标识符,因为它不是一个名称。然而,它确实指定了一个对象,在这种情况下,它与entity指定的对象相同。一般而言,那些指定对象的表达式被称为左值。所以,entity既是标识符,也是左值;*pt既是表达式也是左值。
1.4.

const char * pc = "Behold a string literal";  //注意const的修饰,限定的是指向的内容不能修改,但是并没有限制pc的指向。
		//注意:
		//int const *p;  等价于const int *p;    //指向的内容不能修改 
		//int * const p;		//指针变量本身不能被修改,但是p指向的空间的内容可以修改。
		//int const *const p; //p的指向不能发生改变,p指向的空间也不能改变。

程序根据上边的声明,把相应的字符串字面存储在内存中,内含这些字符值的字符串字面量就是一个对象。由于字符串字面量中得每个字符都能被单独访问,所以每一个字符也是一个对象。该声明还创建了一个标识符为pc的对象,存储着字符串的地址。由于可以设置pc可以重新指向其他字符串,所以标识符pc是一个可以修改的左值。const只能保证被pc指向的字符串内容不被修改,但是无法保证pc不指向别的字符串。

1.5.可以用存储期描述对象,所谓存储器就是指对象在内存中保留多长时间。
1.6.标识符用于访问对象,可以用作用域和链接描述标识符,标识符的作用域和链接表明了程序那些部分可以使用它。

2.1作用域
作用域描述程序中可以访问标识符的区域。一个C变量的作用域可以是块作用域、函数作用域、函数原型作用域、或文件作用域。
2.1.1块作用域:就是一对大括号括起来的区域。块作用域的可见范围是从定义处到包含该定义的块的末尾。另外,虽然函数的形式参数的声明在函数的左花括号之前,但是他们也具有块作用域,属于函数体这个块。所以,局部变量(包括函数的形式参数)都具有块作用域。

以前,具有块作用域的变量都必须声明在块的开头,C99标准放宽了这一限制,允许在块中的任意位置声明变量。因此对于for的循环,现在可以这样写:
for(int i=0; i<10; i++)
	{
		……;
	}
	为适应这个新特性,C99把块的概念扩展到了包括for循环,while循环、do while循环和if语句所控制的代码,即使这些代码没有用花括号括起来,
	也算是块的一部分,所以上边的for循环中的变量i被视为for循环块的一部分,它的作用域仅限于for循环。一旦离开for循环,就不能再访问i.

2.1.2函数作用域: 仅限goto语句的标签,这意味着即使一个标签首次出现在函数的内层块中,它的作用域也延伸至整个函数。如果两个块中使用相同的标签会很乱,标签的函数作用域防止了这样的事情发生。
2.1.3函数原型作用域: 用于函数原型中的形参名(变量名) 如下所示:

int mighty(int mouse ,double large)

函数原型作用域的范围是从形式参数定义处到原型声明结束。这意味着,编译器在处理函数圆形中的形式参数是只关心它的类型,而形参名(如果有的话)通常无关紧要。而且,即使有形参名,也不必要与函数定义中的形参名相匹配。只有在变长数组中,形参名才有用。
变量定义在函数外边,具有文件作用域。具有文件作用域的变量,从它的定义处到该定义所在文件的结尾均可见。具有文件作用域的变量也就是我们所说的全局变量。

注意:
编译器源文件(.c文件)和所有的头文件(这个源文件所包含的所以头文件)都看成是一个包含信息的单独文件。这个文件被称为翻译单元。描述一个具有文件作用域的变量(全局变量)时,它的实际可见范围是整个翻译单元。如果程序有多个源文件,那么该程序也就有多个翻译单元。每个翻译单元均对应一个源代码文件和他所包含的文件。

2.2链接
2.2.1.C变量有三种链接属性:外部链接、内部链接和无链接。
2.2.2.具有块作用域、文件作用域、函数作用域或函数原型作用域的变量都是无链接变量。因为这些变量属于定义它们的块、函数、或者原型私有。具有文件作用域的变量可以是外部链接或内部链接。外部链接变量可以在多文件程序中使用,内部链接变量只能在一个翻译单元中使用。
内部链接的文件作用域:描述仅限一个翻译单元。
外部链接的文件作用域:描述可延伸至其他翻译单元作用域。

2.3存储期
作用域和链接描述了标识符的可见性。存储期描述了通过这些标识符访问的对象的生存期。C对象有4种存储期:静态存储期、线程存储期、自动存储期、动态分配存储期。

如果对象具有静态存储期,那么它在程序的执行期间一直存在。文件作用域变量具有静态存储期。对于文件作用域变量,关键字static表明的是其链接属性,而非存储期。以static声明的文件作用域变量具有内部链接。但无论是内部链接还是外部链接,所有的文件作用域变量都具有静态存储期。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值