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


相关文章
|
2月前
|
存储 编译器 程序员
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
在C语言中,内存布局是程序运行时非常重要的概念。内存布局直接影响程序的性能、稳定性和安全性。理解C程序的内存布局,有助于编写更高效和可靠的代码。本文将详细介绍C程序的内存布局,包括代码段、数据段、堆、栈等部分,并提供相关的示例和应用。
67 5
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
|
2月前
|
存储 编译器 C语言
【C语言】C语言的变量和声明系统性讲解
在C语言中,声明和定义是两个关键概念,分别用于告知编译器变量或函数的存在(声明)和实际创建及分配内存(定义)。声明可以多次出现,而定义只能有一次。声明通常位于头文件中,定义则在源文件中。通过合理组织头文件和源文件,可以提高代码的模块化和可维护性。示例包括全局变量、局部变量、函数、结构体、联合体、数组、字符串、枚举和指针的声明与定义。
72 12
|
2月前
|
存储 缓存 算法
【C语言】内存管理函数详细讲解
在C语言编程中,内存管理是至关重要的。动态内存分配函数允许程序在运行时请求和释放内存,这对于处理不确定大小的数据结构至关重要。以下是C语言内存管理函数的详细讲解,包括每个函数的功能、标准格式、示例代码、代码解释及其输出。
84 6
|
2月前
|
C语言
【C语言】全局搜索变量却找不到定义?原来是因为宏!
使用条件编译和 `extern` 来管理全局变量的定义和声明是一种有效的技术,但应谨慎使用。在可能的情况下,应该优先考虑使用局部变量、函数参数和返回值、静态变量或者更高级的封装技术(如结构体和类)来减少全局变量的使用。
50 5
|
3月前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
85 6
|
3月前
|
大数据 C语言
C 语言动态内存分配 —— 灵活掌控内存资源
C语言动态内存分配使程序在运行时灵活管理内存资源,通过malloc、calloc、realloc和free等函数实现内存的申请与释放,提高内存使用效率,适应不同应用场景需求。
|
3月前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
3月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
92 1
|
3月前
|
存储 算法 C语言
用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容
本文探讨了用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容,旨在为开发者提供全面的指导和灵感。
86 2
|
3月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。

热门文章

最新文章