c语言变量的作用域,链接属性,储存类型&&static关键字

来源:互联网 发布:莎士比亚 知乎 编辑:程序博客网 时间:2024/06/05 15:34

http://blog.csdn.net/mingzhentanwo/article/details/43524383

一、作用域:

变量在程序的某个部分声明时,只能在程序的一定区域内才能访问,这个区域就成为作用域
作用域分为四种:
①文件作用域②函数作用域③代码块作用域④原型作用域。
编译器通过变量声明的位置来确定作用域

(1)文件作用域

当变量在所有代码块之外声明时就在文件作用域中,文件作用域的范围是从变量声明处一直到文件的结束。但如果变量的声明在“.h”文件中,并且该“.h”文件被其他文件用#include 所包含,那该变量的作用域也会相应的扩大到包含文件的结束。

(2)函数作用域

函数作用域只适用于语句标签,语句标签用于goto语句。一个函数作用域内的语句标签必须唯一。

(3)代码块作用域

声明位于一对大括号之间,有效范围从声明开始至代码块结束。

(4)原型作用域

原型作用域 适用于在函数声明中的参数名,只适用于函数声明的括号内;

二、链接属性

链接属性决定如何处理在同一个项目位于不同文件内的标识符。链接属性共有三种——①external(外部)、②internal(内部)、③none(无)。

  • 链接属性为none的标识符不论在那个文件内都是独立的个体
  • 链接属性为internal的标识符在同一个原文件内的所有声明均指向同一个实体,不能在其他文件中使用extern关键字被使用;
  • 链接属性为external的标识符不论声明多少次,位于几个原文件内均表示同一实体,可以在其他文件中使用extern关键字声明使用;

    在文件作用域内声明的变量或是函数,在缺省的条件下链接属性为external(相当于前面加了extern),其余的为none

(1)extern关键字

如果使用externa关键字声明某一个变量,说明该变量在别的地方定义的,可能位于别的文件也可能位于当前文件。该关键字制定标识符的链接属性为external,在一个项目中 ,在一个文件内部可以通过extern关键字访问由别的文件定义的变量,但此时不能在使用extern修饰变量的同时给该变量赋初值

例1:在test2.c文件中使用test1.c文件中的变量a,且变量a属性为external.
会出错: 找到一个或多个多重定义的符号

//test1.c#include<stdio.h>int a=0;void fun1(){    printf("%d\n",a);}
//test2.c#include<stdio.h>int a=1;void fun2(){    printf("%d\n",a);}
//main.c#include<stdio.h>void fun1();void fun2();int main(){    fun1();    fun2();    return 0;}

出错: 找到一个或多个多重定义的符号

例2:在test2.c文件中使用关键字extern声明,使用test1.c文件中的变量a,此时,test2.c中的a值就是test1.c中的a值;且变量a属性为external;然后在main.c中使用extern声明a;此时,在三个源文件中使用的a为一个内存中的a,
这时,三个只要改了一个源文件的a值,三个源文件当中的a值都会改变;
程序正确

//test1.c#include<stdio.h>int a=0;void fun1(){    printf("%d\n",a);}
//test2.c#include<stdio.h>extern int a;a=1void fun2(){    printf("%d\n",a);}
//main.c#include<stdio.h>void fun1();void fun2();int main(){    extern int a;    fun1();    fun2();    a=10;    fun1();    fun2();    return 0;}

//结果:0 ,0 , 10 , 10

(2)static关键字

如果一个标识符的链接属性为external,那么static可以将其链接属性改为intern,此时static修饰的变量或者函数名,都只能在本文件中使用,不能使用extren关键字在别的文件中声明使用;此时别的文件可以命名和静态变量或者函数相同的变量名或者函数名;此时,在别的文件中如果使用extren声明和静态变量的变量名或者函数名相同的名字,并对其变量做改变;此时静态变量或者函数不改变,含有相同名变量的文件里面的变量会改变;
例1、test1.c中定义一个全局静态变量,此时该变量的链接属性从external变为internal;在test2.c中定义了一个和变量名相同的变量;可以成功定义;
此时test2.c中的a的链接属性为external;在main.c中使用extren关键字声明a变量;实际是声明的test2.c中的a变量;在main.c中对a做修改,只是改变了
test.2中的a;

//test1.c#include<stdio.h>static int a=0;void fun1(){    printf("%d\n",a);}
//test2.c#include<stdio.h>int a=10;void fun2(){    printf("%d\n",a);}
#include<stdio.h>void fun1();void fun2();int main(){    extern int a;    fun1();    fun2();    a=100;    fun1();    fun2();    return 0;}

//结果:0 ,10, 0, 100

三、储存类型

储存类型(储存位置)分为普通内存运行时堆栈硬件寄存器
变量的缺省类型取决于它的储存类型:
•在代码块之外声明的变量总是储存在静态内存中,这种变量称为静态变量。无法改变这种变量的储存类型。静态变量在程序运行之前创建,在整个程序运行时一直存在直至结束才被销毁。
•在代码块内声明的变量缺省储存类型为自动的,储存在堆栈内。每次函数被调用时,这些变量的储存的位置可能不同。如果用static来修饰一个函数内的变量,就可以将他转变为静态的,静态储存类型的变量在整个程序执行的过程中一直存在,而不仅仅是在它所在的代码块执行的时候存在,修改变量的储存类型,不会改变的该变量的作用域,它只能在该变量内部按名字访问※只是每次函数被调用时,该变量的值仍为上次函数结束时的值。
•用register修饰的变量成为寄存器变量,通常,这种变量的访问速率比在内存中的变量访问速度快。

四、static关键字

(1)当static用于代码块之外时,static用于修改标识符的链接属性从external修改为static
当static用与代码块内部时,static用于修改标识符的储存类型,将其从自动变量修改为静态变量
这里写图片描述

原创粉丝点击