编辑中。。。未完。。。
一个由c/C++编译的程序占用的内存分为以下几个部分(内存四区)
1、栈区(stack):
由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
栈stack是一种先进后出的内存结构,所有的自动变量,函数的形参都是由编译器自动放出栈中,当一个自动变量超出其作用域时,自动从栈中弹出。
对于自动变量,什么时候入栈,什么时候出栈,是不需要程序控制的,由C语言编译器实现,栈不会很大,一般都是以K为单位的
当栈空间以满,但还往栈内存压变量,这个就叫栈溢出
对于一个32位操作系统,最大管理管理4G内存,其中1G是给操作系统自己用的,剩下的3G都是给用户程序,一个用户程序理论上可以使用3G的内存空间,
2、堆区(heap):
一般由程序员分配释放,若程序员不释放,程序结束时可能由OS操作系统回 收。
注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
堆heap和栈一样,也是一种在程序运行过程中可以随时修改的内存区域,但没有栈那样先进后出的顺序。
堆是一个大容器,它的容量要远远大于栈,但是在C语言中,堆内存空间的申请和释放需要手动通过代码来完成。
3、数据区:
主要包括静态全局区和常量区,如果要站在汇编角度细分的话还可以分为很多小的区。
1全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后有系统释放
2常量区 :常量字符串就是放在这里的。 程序结束后由系统释放
4、 代码区:
存放函数体的二进制代码。代码区code,程序被操作系统加载到内存的时候,所有的可执行代码都加载到代码区,也叫代码段,这块内存是不可以在运行期间修改的。
指针:指针是一种数据类型
指针变量也是一个变量,指针存放的内容是一个地址,该地址指向一块内存空间
指针的步长,根据所指内存空间类型来定。
指针占用字节:汇编书籍对指针比较具体的解释:指针是寄存器和内存字。
寄存器在不同的操作平台上位数是不同的;内存字也是如此。
例如在8086上,内存字就是16位的,而x86系统是32位的。
对于windos的平台,32位的操作系统,寄存器和内存器是32位的。所以就是4个字节;而换到其他的平台,得根据操作平台而定的。就和整形数据在不同平台的数据范围一样。64位系统下是8个字节(64兼容32位,编译器不同会导致64位系统下生成的是32位程序【可以更换编译器】)一般Unix的指针字节数为4
还有种更加直观的解释就是:指针是以内存地址作为变量地址。
野指针解决办法:
1、定义指针时,把指针变量赋值成NULL
2、释放内存是,先判断指针变量是否为NULL
3、释放完内存后,把指针变量重新复制成NULL
一级指针易错点:
1、不断修改指针的指向,然后又free和printf(重复free或操作已经被释放的内存单元)
2、Char buf[3] = “asc” ;//越界问题
3、*p++与(*p)++.;前者是指针++,后者是数据++
一遍可能定义一个变量计数值的时候用*count++,错误用法
还有就是求字符串的时候指针指向改变,然后释放该内存的时候出错
1、 还有就是被调用函数分配临时空间,然后把该临时空间首地址返回出来出错
2、 解决的方法有多种,一般字符串指针的时候用两个指针,一个用于记录首地址
3、 为什么int a[10];中a是个常量 ,a++;//这里会报错,为什么数组首地址不能++
因为a是数组类型的内存块的首地址,这数组是个临时变量。编译器要拿着首地址a去释放内存,为了避免你把a 的指向改变所以设置为常量(数组的首地址是常量,不可改变)
指针的最大意义:指针做函数参数间接赋值是指针存在的最大意义
将函数指针做为另一个函数的参数称为回调函数
指针小结:
定义 | 说明 |
int i | 定义整形变量 |
int *p | 定义一个指向int的指针变量 |
int a[10] | 定义一个int数组 |
int *p[10] | 定义一个指针数组,其中每个数组元素指向一个int型变量的地址 |
int (*p)[10] | 定义一个数组指针,指向int [10]类型的指针变量 |
int func() | 定义一个函数,返回值为int型 |
int *func() | 定义一个函数,返回值为int *型 |
int (*p)() | 定义一个指向函数的指针,函数的原型为无参数,返回值为int |
int **p | 定义一个指向int的指针的指针,二级指针 |
1)指针也是一种数据类型,指针的数据类型是指它所指向内存空间的数据类型
2)间接赋值*p是指针存在的最大意义
3)理解指针必须和内存四区概念相结合
4)应用指针必须和函数调用相结合(指针做函数参数)
5)指针指向谁就把谁的地址赋给指针
6)指针指向谁就把谁的地址赋给指针,用它对付链表轻松加愉快
7)链表入门的关键是分清楚链表操作和辅助指针变量之间的逻辑关系
数组在内存的存储方式:数组在内存中就是一段连续的空间,每个元素的类型是一样的
结构体的内存对齐模式
结构体的赋值(深拷贝和浅拷贝)
文件
作为接近底层的高级语言,c语言的代码中,允许嵌入汇编语言。在某种情况下,用汇编语言替代高级语言,可以大大提高运行效率。
int main()
{
int a = 10;
_asm //汇编指令
{
mov eax,a //移动,将a的值赋值eax
add eax,3 //加法,eax的值+3
mov a ,eax //寄存器的值赋值给a
}
printf("%d", a);
return 0;
}