程序加载到内存后,操作系统会给不同的内存指定不同的权限,拥有读取和执行权限的内存块是代码,拥有读取和写入权限的内存块是数据
CPU一般通过地址来取得内存中的代码和数据
CPU访问内存时需要的是地址,而不是变量名和函数名,当源文件被编译和链接成可执行程序后,都会被替换成地址
(变量名是数据,函数、字符串名、数组名是代码块或数据的首地址)
程序在硬盘中,要载入内存才能运行
CPU只能从内存中读取数据和指令
对于CPU,内存时存放指令和数据,并不能完成计算功能
计算机:硬盘->内存->CPU:缓存->>
CPU=运算器+寄存器+缓存寄存器:一个寄存器能够存储32/64位的数据,CPU一般由上百个寄存器(多少位的计算机,表示的是寄存器是多少位的)。寄存器用来进行数学运算或流程控制
缓存:内存读取速度小于CPU,因此将频繁使用的数据暂时读取到缓存区。CPU只能从缓存中读取到部分数据,对于使用不是很频繁的数据会直接从内存中读取。
数据以二进制的形式保存在内存中,字节是最小的可操作单位
在内存管理中,为每个字节分配了一个编号,使用该字节时,只要知道编号就可以,这个编号,就是地址
获取地址
&data
,(data可以是数值、字符)
编译器自动分配
局部变量、形参、返回值,const
定义的局部变量也存放在栈区
操作系统自动管理
栈区上的内容只在函数范围内存在,函数结束自动销毁
栈区内存地址:由高到低,即后定义的变量地址低于先定义的变量地址
先进后出
属于动态内存分配
函数中定义的局部变量按照先后定义的顺序一次压入栈中,即,相邻变量的地址之间不会存在其他变量
程序员分配内存和释放,若开发人员不释放,程序结束时有系统回收
malloc()
free()
new
delete
堆区内存地址:由低到高
大小由系统内存/虚拟内存上限决定
属于动态内存分配
注意:后申请的内存空间并不一定在先申请的内存空间的后面,因为先申请的内存空间一旦释放,后申请的内存空间则会利用先前被释放的内存,从而导致先后分配的内存空间在地址上不存在先后关系
堆中存储的数据若未释放,则生命周期等同于程序的生命周期
由于系统是通过链表来存储空闲的内存地址,因此堆数据时不连续的内存空间
对于堆分配,操作系统有一个记录空闲内存地址的链表,当申请内存时,会遍历该链表,寻找第一个空间大于所申请空间的堆节点,然后将该节点从空闲节点链表中删除,并将该节点的内存空间分配给程序。另外,对于大多数系统,会在这块内存空间中的首地址出记录本次分配的大小,这样使用delete才能正确释放内存空间。由于找到的堆节点的大小不一定正好等于申请的大小,系统会自动将多余的部分重新放入空间链表
// c 用malloc// 注意指针的类型转换
char* p1=(char*)malloc(10);
free(p1);
//free(p)并不能改变指针p的值,p依然指向以前的内存,为了防止再次使用该内存,建议将p的值手动置为NULL// C++ 用new
char* p2=new char[10];
delete[] p2
未初始化全局(静态)区 .bass
已初始化全局(静态)区 .data
在编译期间就能确定 存储大小的变量 的存储区,
包括全局变量,静态变量(包括静态全局变量、静态局部变量)
属于静态内存分配
.bass
读写
未初始化的全局变量或未初始化的静态变量
初始化为0的全局变量或初始化为0的静态变量
.bass段不占用可执行文件空间,由操作系统初始化
.data
读写
已初始化的全局变量 (但初始化不为0的)
已初始化的静态变量 (但初始化不为0的)
.data段占用可执行文件空间,由程序初始化
.rodata
字符、字面值、字符串等常量
const 修饰的全局变量(const修饰的局部变量存放在栈区)
运行期间,常量区的内容不可被修改
属于静态内存分配
存放程序的代码 .txt
只读
属于静态内存分配
不可修改
代码区、常量区、全局数据区的内存在程序启动时就已经分配好了,大小固定、不能由程序分配或释放,只能等到程序运行结束由操作系统回收
栈区、堆区的内存在程序运行期间可以根据实际需求来分配和释放,不用在程序刚启动时就备足所有内存
一块内存没有被指针指向它,(程序和内存失去了联系,再无法对他进行任何操作),这块内存直到程序结束被系统回收
内存中用于临时保存输入输出数据
缓冲区 :内存空间的一部分
作用: 减少磁盘的读写次数 ;
分类输入缓冲区/输出缓冲区
根据数据刷新时机全缓冲:缓冲区被填满时(一般是对硬盘的读写)
行缓冲:遇到换行符时 (标准I/O),prinf(“\n”),scanf回车
无缓冲: getche(),getch() 这两个函数没有缓冲
(程序结束的时候 也会刷新缓冲区)
(输出之后有输入的操作,也会刷新缓冲区)注意:不同的操作系统对缓冲区的定义时不同的,printf在windows下无需缓冲,在linux下有缓冲
不刷新缓冲区的例子
// 这个例子,进入死循环
// 缓冲区没有被填满、没有遇到换行符、程序没有结束,所以标准输出始终没有显示字符串
int main()
{printf("hello world"); // 只要加上printf("hello world\n") 立即刷新while (1);return 0;
}
刷新
行缓冲,全缓冲:缓冲区满时自动刷新
行缓冲:遇到’\n’时,自动刷新
关闭文件时自动刷新
程序关闭时自动刷新
使用刷新函数
清空输出缓冲区
fflush(stdout) // 一般用于linux系统下,清空标准输出缓冲区,清空屏幕缓冲区
清空输入缓冲区
int c
while (c=getchar()!='\n' && c!=EOF)
FILE *fp;FILE 结构体
int cn // 剩余字符,缓冲区中还有多少个字符未被读取
char *ptr //下一个要被读取的字符的地址
char *base // 缓冲区的基地址
int flag // 读写状态标志位
int fd // 文件描述符
FILE是文件缓冲区的结构体,fp是指向文件缓冲区的指针
缓冲区的刷新表示将 缓冲区的指针变为缓冲区的基地址
上一篇:JVM之方法的调用
下一篇:Cyclone DDS(初识)