位于一对花括号之间所有的语句称之为一个代码块。任何在代码块开始位置声明的标识符都具有代码块作用域,表示它们可以被这个代码块中所有的语句访问。但是,内层嵌套的语句和外层的标识符同名时,内层的那个标识符会覆盖外层的那个同名的标识符
任何在代码块之外声明的标识符都具有文件作用域,它表示这些标识符从它们的声明之处直到它所在的文件结尾处都是可以访问的,并且我们在函数中定义的函数名也具有文件作用域。要注意的是,在头文件中编写并且通过#include指令包含到其他文件中的声明就好像是它们直接写在那些文件中一样。它们的作用域并不局限于头文件的文件尾。
原型作用域只适合用于在函数原型中声明的参数名
函数作用域,它只适合用于语句标签,语句标签用于goto语句
当组成一个程序的各个源文件分别被编译之后,所有的目标文件以及那些从一个或多个函数库中的引用的函数链接在一起,形成可执行文件。但是当相同的标识符出现在几个不同的源文件中时,它们是表示同一个实体还是不同的实体?标识符的链接属性决定如何处理在不同文件中出现的标识符。标识符的作用域与它的链接属性有关,但两个属性并不相同;
属于external链接属性的标识符不论声明多少次,位于几个源文件都表示同一个实体;
属于internal的链接属性的标识符在同一个源文件当中都指向同一个实体,但是位于不同原文件的多个声明则分属不同的实体;
没有链接属性的标识符(none),总是别当作单独的个体,也就是说该标识符的多个声明被当作独立不同的实体;
关键字extern和static用于在声明中修改标识符的链接属性,如果某个标识符具有external链接属性,加上static则此标识符的链接属性就会变为internal。注意static只对缺省属性为external的声明才有效
extern关键字为一个标识符指定external链接属性,这样我们就可以在其它任何位置访问这个标识符的实体
变量的缺省存储类型取决于它的声明位置。凡是在任何代码块之外声明的变量总是存储于静态内存中,也就是不属于堆栈的内存。静态变量创建于程序运行之前,在整个程序的执行期间都存在,他始终都保存原先的值,除非付给他一个不同的值,或则程序结束;
在代码块内部声明的变量的缺省存储类型是是自动的,也就是说它存储在堆栈中,称为自动变量;但是假如我们给在代码块中定义的变量加上static,那么它的存储类型就会变为静态类型,但是它的作用于不变(前面讲过static修改链接属性只对原本的链接属性为external才有用,而代码块中定义的缺省都为internal);
在变量前面加上register,可以用于自动变量的声明,提示他们应该存储于机器的硬件存储器而不是内存中,这类变量称为寄存器变量;但是这种定义不一定会起作用,由编译器来决定
1:auto 自动变量(动态存储)
声明中有auto修饰符时,具有动态存储周期。这种修饰符只能用于函数内部的对象声明。在ANSIC中,默认情况下函数内部都有动态的存储周期,所以不需要用修饰符auto
2:register 寄存器变量(动态存储)
当声明的对象有动态存储周期时,可以使用修饰符register.关键字告诉编译器,所声明对象的访问应该尽快,应该将对象保存在寄存器中,但最终决定由编译器给出
3:extern 外部变量(静态存储)
被声明为extern的函数和对象标识符具有外部链接。可以在程序中任何地方使用这些标识符。外部对象具有静态的存储周期
4:static 静态变量(静态存储)
被声明为static的函数具有内部链接,换句话说,别的翻译单元无法使用所声明的函数标识符来访问函数
在c语言中定义就是把一个符号完整的描述出来:它是变量还是函数,返回什么类型,需要什么参数等等;而声明则只是声明这个符号的存在,即告诉编译器这个符号实在其它文件文件中定义的。定义的时候我们需要按照c的语法完整的定义一个符号,而声明的时候就只需要写出这个符号的原型了;
头文件实际上就是我们存放声明语句的地方
源文件其实就是存放我们定义(实现)代码的地方
编译器将源文件编译成目标文件,目标文件就是我们的编译单元。一个程序可以由一个编译单元组成,也可以由多个编译单元组成。一个函数不能放到两个编译单元里面,但两个函数或以上就可以分别放在一个单元里面。那么就是一个源文件对应一个目标文件,然后通过链接器组成一个.exe,也就是程序了。
在c++中,使用函数或则变量之前必须要进行声明。那么如果一个源文件要用到另一个源文件定义的函数,只需要在这个源文件中写上它的函数声明就可以了,其余工作由链接器来完成。但是但多个文件都需要使用同一个函数时,那么就要在多份源文件中进行声明,而且如果需要修改这个函数时就必须逐个修改每个源文件。
头文件(.h)就是为了解决这个问题而诞生,它包含了这些公共的函数定义,而且如果需要修改,也只修改头文件的内容即可。
对于将实现放在头文件中的几点考虑:
3.头文件被包含到不同的源文件中,会导致有多份实现被编译出来,增大可执行体的体积