基础概念
stack
内存中的一个特殊区域,用于存储由每个函数(包括main()函数)参数传递的本地数据,返回地址。
堆栈是一个 LIFO(后进先出)数据结构,该结构由CPU非常紧密地管理和优化。每当函数声明一个新变量时,它都会push到堆栈中。 然后,当一个函数退出时,它的所有变量都会从堆栈中弹出(也就是说,它们将被删除)。释放堆栈变量后,该内存区域可用于其他堆栈变量。
无需亲自管理内存,变量会自动分配和释放,堆栈有大小限制(os分配),堆栈变量仅在创建它们的函数运行时存在, 快速访问(堆栈速度更快,因为所有可用内存始终是连续的。不需要维护所有可用内存段的列表,只需一个指向堆栈当前顶部的指针即可。)
CPU有效管理空间,内存不会碎片化,堆栈指针指向堆栈的顶部(堆栈中的最高地址)由高到低地址,堆栈增长到底部
由于堆栈是有限的内存块,调用过多的嵌套函数、无限递归或为局部变量分配过多的空间而导致堆栈溢出
heap
要主动分配和释放变量,有很多分配和释放时,可能会产生碎片。变量可以全局访问,内存大小无限制(物理限制)。堆内存的读取和写入速度稍慢,因为必须使用指针来访问堆上的内存
随着堆的增长,通常将新块从低地址分配到高地址。随着分配的内存,存储块的大小会增加。
分配大块的请求可能会失败,因为即使空闲块的组合大小可能足够大,也没有一个空闲块足以满足分配请求。这称为堆碎片。 当与空闲块相邻的已用块被释放时,新的空闲块可以与相邻的空闲块合并以创建更大的空闲块,从而有效地减少了堆的碎片。
全局(静态)存储区
分为DATA段和BSS段。
-
DATA段(全局初始化区)存放初始化的全局变量和静态变量
-
BSS段(全局未初始化区)存放未初始化的全局变量和静态变量。
程序运行结束时自动释放。其中BBS段在程序执行之前会被系统自动清0,所以未初始化的全局变量和静态变量在程序执行之前已经为0。
程序主要包括以下部分
- 预处理器指令
- 函数
- 变量
- 语句 & 表达式
- 注释
1 |
|
gcc 命令如果不指定目标文件名时默认生成的可执行文件名为 a.out(linux) 或 a.exe(windows)。
可用 gcc [源文件名] -o [目标文件名] 来指定目标文件路径及文件名。
标识符
C 标识符是用来标识变量、函数,或任何其他用户自定义项目的名称。一个标识符以字母 A-Z 或 a-z 或下划线 _ 开始,后跟零个或多个字母、下划线和数字(0-9)。
C 标识符内不允许出现标点字符,比如 @、$ 和 %。C 是区分大小写的编程语言。
变量
1 |
|
声明之后你不能直接使用这个变量,一个变量一定要先初始化才可以使用,因为 c 语言中默认一个没有初始化的变量值是一个不可知的很大值。定义只能出现在一处。变量越先定义,内存地址就越大。
常量
1 |
|
有两种简单的定义常量的方式:
-
使用 #define 预处理器。 宏替换只作替换,不做计算,不做表达式求解
-
使用 const 关键字。编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
1 |
|
static
static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。
修饰局部变量可以在函数调用之间保持局部变量的值。
修饰符全局变量会使变量的作用域限制在声明它的文件内。全局声明的一个 static 变量或方法可以被任何函数或方法调用,只要这些方法出现在跟 static 变量或方法同一个文件中。
只会被初始化一次,不会在每次调用时重置
1 |
|
extern
存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。当您使用 extern 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。
当您有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。
extern 修饰符通常用于当有两个或多个文件共享相同的全局变量或函数
结构
1 |
|
函数
1 |
|
数组
1 |
|
指针
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。
1 |
|
结构体
1 |
|
头文件
一个头文件被引用两次,编译器会处理两次头文件的内容,这将产生错误。
1 |
|
可变参数
1 |
|