(1)作用域:
<1>编译器可以有4种不同类型的作用域:文件作用域、函数、代码块、原型作用域:
代码块作用域:(block scope)用{。。。。。}括起来的部分;
文件作用域:任何在代码块外部声明的标示符都具有文件作用域;
原型作用域:(prototype scope)只适用于在函数原型中声明的参数名;
函数作用域:只适用于语句标签,语句标签用于goto语句,一个函数中的所有语句标签必须唯一;
<2>因为不重叠的代码块变量不可能同时存在,所以编译器可以把它们存储于同一个内存地址内。
<3>函数形参的作用域为函数最外层那个作用域,这样函数最外层作用域的局部变量无法与形参同名。
<4>在头文件中通过#include包含的文件中的声明不只局限于头文件尾的作用域,就好像直 接写在包含该头文件的文件中一样。
(2)链接属性:
<1>各个源文件被编译后,所有的目标文件+从函数库中引用的函数(一般是归档库文件,*.a 类型)经过链接器链接,形成一定格式的可执行程序,如elf格式。如果相同的标示符出现在几个不同源文件中,他们是否表示同一个实体。这由标示符的链接属(linkage)决定。标示符的作用域和链接属性相关,作用域是由链接属性决定的,但二者并不相同。
<2>链接属性分类:外部(external),内部(internal),无(none)。
①外部属性:标示符在整个程序内,不论出现于哪个文件,不论声明多少次,都指的同一个实体。
②内部属性:只在同一个源文件的所有声明中指同一个实体。
③无属性:该标示符的多个声明都被当做独立的个体。
<3>文件作用域中声明的变量或者函数默认情况下是外部属性(相当于前面加了extern)
<4>static可以改变变量或者函数的链接属性,使其从外部属性变成内部属性,防止被其他文件使用,static只对缺省属性为external的声明才有改变链接属性的效果。
<5>链接属性由第一次声明决定,extern与static都无法再次改变其链接属性,如果extern在声明的同时进行初始化则变成了定义。
(3)存储类型:
<1>变量的存储类型(storage class)是指存储变量值的内存类型。变量的存储类型决定了变量何时创建,何时销毁以及它的值保持多久。
<2>有三个地方可以用于存储变量:普通内存,运行时堆栈,硬件寄存器。
<3>变量的存储类型取决于它的声明位置:
1)在任何代码块之外声明的变量总是存储于静态内存(程序的数据段+bss段,BSS(Block Started by Symbol)通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。静态变量在程序运行之前创建,在程序的整个执行过程中都存在。
2)在代码块内声明的变量默认是自动变量(automatic),存储于堆栈中,这类变量叫做自动(auto)变量。在程序执行到该代码块时,内部的自动变量才被创建,当程序离开该代码块时,自动变量销毁。在代码块内部的变量或者函数如果给它加上static关键字,可以使其变为静态变量。.修改变量的存储类型,不等于修改变量的作用域,它仍然只能在该代码块内部按名字访问。函数的形式参数不能声明为静态,因为函数的参数传递是通过堆栈进行的,用于支持递归。
3)在变量前加上register关键字,可以告诉编译器该变量应该存储于机器的硬件寄存器,而不是内存。如果有很多register变量,编译器只会选几个变量存储于寄存器。函数形参可以为寄存器变量。在一个使用寄存器变量的函数返回前,这个寄存器先前存储的值必须恢复。