内存各分区数据类型
序号 | 内存分区 | 数据类型 | 说明 |
| 代码段 | 可执行程序 | 文本段(.text) |
| 只读数据段 | const常量 | 不同平台不同,下载程序时写入数据 |
| 数据段 | 非0全局常量 非0局部静态量 | - |
| bbs段 | 为0全局常量 为0局部静态量 | - |
| 堆 | 默认:无 | 默认无,程序员malloc申请使用 |
| 文件映射区 | 文件临存 | 文本编辑时,点击保存时写入硬盘 |
| 栈 | 局部变量、形参 | - |
| 内核映射区 | 操作系统 | 见详解 |
内核映射分区
操作系统内核映射区域中每个进程都只能看到自己和内核,进程间相互隔离。操作系统给每个进程虚拟地址都是0开始。
操作系统os内核 | |||
进 程 1 (3G) | 进 程 2 (3G) | 进 程 3 (3G) | 进 程 4 (3G) |
裸机和系统编程差异
裸机代码需要自己搭建c运行环境(如:重定位、清bbs,全局变量赋值)。操作系统上运行则不需要自己处理c环境,系统会为其处理,且数据段的变量在程序执行前就已经有值了,是重定位实现的。
c关键字属性
代码块
程序中一对大括号间的所有代码,被称为代码块。
关键字 | 功 能 | 作用域 | 生命周期 | 链接属性 |
auto | 修饰变量为局部(默认) | 申明后的代码块 | 代码块内 | 无链接 |
static | 修饰静态局部变量 | 申明后的代码块 | 程序开始到结束 | 无链接 |
全局变量、函数作用域修饰 | 单文件作用域 | 程序开始到结束 | 外链接 | |
register | 修饰变量优选寄存器存储 | 修饰不同类型变量其属性不同 | ||
extern | 外部全局变量声明 | 通常修饰全局变量其属性遵循全局变量规则 | ||
volatile | 修饰变量会被硬件改变 | 修饰不同类型变量其属性不同 | ||
restrict | 只修饰指针指向的变量仅本指针改变 | 修饰不同类型变量其属性不同 |
auto
只能用来修饰局部变量,表示是自动局部变量,会被分配到栈,默认的普通局部变量类型都是auto,无需特意申明修饰。
static
static在c中有完全不同的2个功能,截然不同的含义;
第一种
静态局部变量修饰;与普通局部变量的区别,是存储类即存储位置不同。
静态局部变量的存储类、生命周期、与全局变量一样。但作用域和链接属性不同;静态变量的作用域是代码块作用域,链接属性是无链接;全局变量的作用域是文件作用域,和函数一样,链接属性是外连接。
第二种
静态全局变量修饰;全局变量的静态和动态的区别主要是链接属性不同。
普通的函数和全局变量是外部链接属性,为了防止文件间重名,所以用static用来修饰全局变量和函数的属性为内部链接属性。
register
用来修饰变量,希望编译器将其变量分配到寄存器中(有空闲寄存器才能执行)。特点是读写特别快,一般变量在高频率使用时,提升程序运行效率。
extern
声明全局变量,在不同文件之间可以被互相被引用。
volatile
volatile释义为可变的,易变的,在程序总用来告诉编译器,这个值会在编译器不知情的情况下修改,任何时候编译器都不能去优化这个变量。
例如:
a=3; b=a;c=b; //编译器会优化成a=3;b=3;c=3;即写3次读1次;
//不优化则需要各读3次,写3次;
特殊情况下,如b=a前a被中断改变,那么编译器优化则是错误的。
volatile 则是告诉编译器不能优化,这个变量有第3方改变。
restrict
c99标准中才支持的c关键字,只修饰指针,告诉编译器该指针指向的对象,只有本指针修改,其它地方都不能修改。
变量作用域
指变量或函数的访问范围,如局部变量只能在函数内访问。
代码块作用域:指一对大括号内{ };
文件作用域:全局访问权限,整个.c文件都可以访问。
局部变量:作用域是定义之后的代码块即{ }之间,出了括号以外就被回收了;
函数和全局变量:作用域是定义之后的整个.c文件。
同名变量的掩蔽规则
同名变量的作用域没有交叉的时候,不受影响。如果有交叉(如全局变量与局部变量名相同),作用域小的有效。作用域大的被掩蔽。
变量的生命周期
栈变量的生命周期
局部变量,生命周期使临时的,如函数内的变量在函数被调用时被建立,函数结束时消亡。
堆变量的生命周期
堆内存是操作系统维护,一直都存在,进程申请时就给进程用,对进程来说就诞生了,用完归还后就结束了。
数据段、bbs段变量生命周期
全局变量,程序开始执行时就诞生,不能由程序自己释放,不管用不用都会被占用,所以要少用全局变量,优选malloc;
代码段、只读段的生命周期
除了代码,部分const和字符串常量被放在代码段,上电诞生,断电消亡。
链接属性
程序由多个.c和.h文件构成,编译就是将其变成多个.o文件,链接则是将多个.o文件链接成1个整体的可执行文件。编译时以文件为单位,链接这是以工程为单位。而链接分为外链接和内链接。
外连接
基于工程内所有文件,垮文件访问。如函数和全局变量。
内链接
.c文件内进行连接,不能跨文件访问,如static修饰的全局变量和函数;
无链接
符号不参与连接,如局部变量。
函数与全局变量的同名冲突:
函数和全局的作用域范围都是整个工程,函数与全局变量同名会出问题,c的解决措施是将不会被外部文件使用的变量和函数使用static修饰成文件内部,避免文件间的重复。
章节总结
存储类,决定生命周期;作用域,决定链接属性;宏和inline的链接属性为无链接。
局部变量 | 静态局部变量 | 全局变量 | 静态全局变量 | 函数 | |
存储位置 | 栈 | 数据段/bbs段 | 数据段/bbs段 | 数据段/bbs段 | 代码段 |
地址变化 | 随机 | 固定 | 固定 | 固定 | 固定 |
默认初值 | 随机 | 0 | 0 | 0 | - |
链接属性 | 无链接 | 无链接 | 外部链接 | 内链接 | 外链接 |
作用域 | 代码块 | 代码块 | 工程内 | 工程内 | 工程内 |
生命周期 | 代码块 | 永久 | 永久 | 永久 | 永久 |