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

简介:

我们都知道在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修饰的函数是可以放在有文件中的,并且不会城乡重复定义)。全局变量的外连接属性就决定了其必须是文件作用域以及永久的生命周期。


本文转自 菜鸟养成记 51CTO博客,原文链接:http://blog.51cto.com/11674570/1870075


相关文章
|
19天前
|
C语言
C语言:内存函数(memcpy memmove memset memcmp使用)
C语言:内存函数(memcpy memmove memset memcmp使用)
|
1天前
|
存储 安全 Java
Python中的引用和赋值机制允许变量引用内存中的对象,并通过引用计数来管理对象的生命周期
【5月更文挑战第14天】Python中的变量是对象引用,不存储数据,而是在内存中创建对象。赋值操作创建新变量并使其指向已有对象。引用计数用于管理对象生命周期,引用数为0时对象被回收。理解这些机制对编写高效Python代码很重要。
14 6
|
5天前
|
存储 程序员 编译器
C语言:动态内存管理
C语言:动态内存管理
10 1
|
5天前
|
存储 编译器 程序员
C语言:数据在内存中的存储
C语言:数据在内存中的存储
13 2
|
5天前
|
存储 编译器 C语言
C语言:字符函数 & 字符串函数 & 内存函数
C语言:字符函数 & 字符串函数 & 内存函数
14 2
|
14天前
|
存储 C语言 开发者
【C言专栏】C 语言实现动态内存分配
【4月更文挑战第30天】C语言中的动态内存分配允许程序运行时按需分配内存,提供处理未知数据量的灵活性。这涉及`malloc()`, `calloc()`, `realloc()`, 和 `free()`四个标准库函数。`malloc()`分配指定大小的内存,`calloc()`同时初始化为零,`realloc()`调整内存大小,而`free()`释放内存。开发者需谨慎处理内存泄漏和指针使用,确保程序的稳定性和性能。动态内存分配是C语言中的重要技能,但也需要良好的内存管理实践。
|
14天前
|
存储 程序员 C语言
C语言进阶第九课 --------动态内存管理-2
C语言进阶第九课 --------动态内存管理
|
14天前
|
编译器 C语言
C语言进阶第九课 --------动态内存管理-1
C语言进阶第九课 --------动态内存管理
|
19天前
|
程序员 编译器 C语言
C语言知识:动态内存管理(malloc free calloc realloc)
C语言知识:动态内存管理(malloc free calloc realloc)
|
19天前
|
存储 编译器 C语言
C语言基础知识:数据在内存中的存储解析(整数,浮点数)
C语言基础知识:数据在内存中的存储解析(整数,浮点数)