C语言之从内存角度理解不同类型的变量

原创 2016-11-08 10:05:31 579
摘要:我们都知道在C语言中不同类型的变量在内存中的存放位置不同的,从内存角度上讲,不同内存块中存放的代码或者变量其属性(主要是作用域、生命周期、链接属性)是不同的。首先我们介绍一下作用域、生命周期已经链接属性的概念1:作用域作用域也就是指变量其作用的范围    (1)局部变量为代码块作用域(也就是说局部变量的作用范围是{  })  &

我们都知道在C语言中不同类型的变量在内存中的存放位置不同的,从内存角度上讲,不同内存块中存放的代码或者变量其属性(主要是作用域、生命周期、链接属性)是不同的。

首先我们介绍一下作用域、生命周期已经链接属性的概念


1:作用域

作用域也就是指变量其作用的范围

    (1)局部变量为代码块作用域(也就是说局部变量的作用范围是{  })

    (2)函数和全局变量是文件作用域,进一步讲其作用范围就是函数和全局变量定义或者声明后的部分。


2:生命周期

  生命周期也就是变量的产生时间和消亡时间

    (1)栈变量的生命周期:局部变量是被分配到栈上面的(栈变量),其生命周期是临时的,临时的意思是按需要去创建、使用、消亡。比如在一个子函数里面定义了一个局部变量int a;那么当这个子函数被调用执行的时候,局部变量int a;会被创建在栈上面(符号a和栈上面的某个内存相绑定),当这个子函数被调用结束时,局部变量int a就消亡了(取消符号a和栈上面的某个内存的绑定),很现实的一个例子就是,当我们写个程序去读取局部变量的地址时,每次读取的地址值是不一样的。

    (2)堆变量的生命周期

首先需要明白一点,堆内存空间是客观存在的,它是由系统维护的一段内存空间,程序员只是向系统申请堆内存,然后释放,所以堆变量也是有生命周期的,其生命周期就是mallloc(返回申请堆内存的首地址)申请到free释放,

    (3)数据段、bss段的生命周期

全局变量的生命周期是永久的,永久的意思是从被定义开始,一直到程序结束。

    (4)代码段、只读段的生命周期

代码段存放的是程序执行的代码(也就是函数),它的生命周期是永久的,但是一般不去研究代码的生命周期,需要注意的是放在代码段的还有const修饰的常量和字符常量(const类型的常量、字符串常量有时候放在rodata段,有时候放在代码段,取决于平台)


3:链接属性

链接属性是指代码在链接时的属性,包括外连接、内链接、无链接三种

    (1)外连接:意思是外部链接属性,也就是说可以在整个程序范围(可以跨文件)内进行链接

    (2)内链接:意思是内部链接属性,也就是说可以在当前c文件范围内进行链接

    (3)无链接:意思是这个符号本身不参与链接,所有的局部变量(auto的,static的)都是无链接的


注意这里还涉及一个同名变量屏蔽规则的问题

    (1)问题:编程时,不可避免会出现同名变量。变量同名后不一定会出错。

    (2)首先,如果两个同名变量作用域不同且没有交叠,这种情况下同名没有任何影响。比如两个子函数里面都定义了局部变量int a;

    (3)其次,如果两个同名变量作用域有交叠,C语言规定在作用域交叠范围内,

作用域小的一个变量会掩蔽掉作用域大的那个(就小范围原则)。比如定义了一个全局变量int a;又在子函数定义了局部变量int a;那么在这个子函数里面起作用的就是局部变量int a;


接下来从变量的类型角度出发,分析代码这三打要素具体到不同变量中的意义


1:普通局部变量

    作用域为代码块作用域,生命周期为临时性生命周期,链接属性为无链接

普通局部变量被分配到栈上面,是按需创建、使用、消亡的,栈每次分配给变量是的地址是不确定的(随机分配)这就决定了其链接属性是无链接。


2:静态局部变量(static修饰的局部变量)

    静态局部变量被分配到了数据段或者bss段(显示初始化为非0则被分配到数据段,未显式初始化或者显式初始化为0则被分配到bss段),作用域为代码块作用域,生命周期为永久性生命周期,链接属性为无链接(因为它的作用域是代码块作用域)。因为静态局部变量被分配到了数据段或者bss段,所以它的生命周期是永久的,所分配的地址和静态局部变量的符号的绑定是不变的,直到程序结束,所以在一个程序中多次使用同一个静态局部变量时其实操作的是同一段内存,因为有这一特性,所以静态局部变量常用来统计子函数被调用的次数。


3:全局变量和普通函数

    作用域为文件作用域,生命周期为永久,链接属性为外连接

需要注意的是全局变量和函数不要在头文件中定义,原因是一个程序多处调用这个头文件(头文件中的内容在被预处理的时候是在文件中原地展开的)时就会出现重复定义(当然使用inline修饰的函数是可以放在有文件中的,并且不会城乡重复定义)。全局变量的外连接属性就决定了其必须是文件作用域以及永久的生命周期。


发布手记

热门词条