关于内存分配

文章目录
  1. 内存
  2. 地址与内容
  3. 指针
  4. 指针变量
  5. 指针的功能
  6. 寻址空间
  7. 动态内存分配
  8. 内存功能区

内存

计算机的内存是算计亿万计的位(bit)组成的, 每个位非0即1 ,但是在计算机中单独的位用处不大, 通常将8个位组合在一起作为一个单位来存储较大的值,这个单位叫做字节(Byte),每个字节通过地址来标识, 真实内存的结构如下图所示:

内存

如果我们想要存储更大的值, 就要把多个字节合在一起作为更大的存储单位, 许多机器以字(word)为单位存储整数, 每个字一般有2或者4个字节.如图:

内存

  • 注意: 尽管一个字包含了4个字节, 但是仍然只有一个地址.

地址与内容

内存

上面这幅图显示了5个字所存储的内容, 并且由地址唯一确定, 如果你拥有了一个值的内存地址, 就可以根据这个地址来获取这个值,这个内存地址叫做指针, 但是在高级程序语言中使用地址太不方便, 所以要通过名字而不是地址来访问存储的内容, 如图所示:

内存

这些名字就是变量, 我们成为指针变量, 就是存放内存地址的变量, 名字地址的映射关系是由编译器实现的, 但是在底层硬件中依然是用地址来访问内存, 名字只是在编程中提供方便记住的方法.

指针

  • 变量的值存储于计算机的内存中,每个变量都占据一个特定的位置, 这个位置由地址唯一确定(并引用) , 就像一条街上的门牌号一样, 当我们引用了这个地址, 就可以操作这块内存空间.
  • 指针:一个操作受限的非负整数(地址加乘除没有意义,可以相减)

指针只能访问动态变量的地址或者本函数中静态变量的地址,即在使用之前没有被释放,静态变量因此不能跨函数使用,因为使用完内存空间被释放,无法访问,比如:
int* p:p也是个变量但只能存放某类型的地址的变量,int* 表示存放整型变量类型地址的变量,p只能存放整形变量(int age = 3)的地址;double*:只能存放double类型的变量地址;char*同理,

指针变量

  • 提起指针一般含有两层含义, 在不同的上下文下含义不一样 , 一种是内存空间的地址, 就是一块内存空间的标识 , 跟门牌号一样, 地址是一个固定不变的值; 另一种是指针变量,即存放地址的变量

  • 指针就是地址,地址就是指针;地址就是内存单元的编号,所以指针只是一个,不是变量,不可以改变;

  • 指针变量存放地址的变量,可以存放地址,是变量,可以改变。

注意:通常在表述时,指针就是指针变量,把变量省去,具体情况具体分析!!!

指针的功能

  1. 表示一些复杂的数据结构
  2. 直接访问硬件地址
  3. 方便的处理字符串
  4. 使函数返回上一个值
  5. 理解OOP中的“引用”概念

指针变量不能相加和相除,可以相加减,*(p+1)其地址移动的位数与该指针类型有关,因为不同类型占用的字节数不一样.

寻址空间

下面看一个有趣的问题:

为什么32位的系统最大内存空间为4G?

  • 首先, 要区分bitByte的概念, bit表示位, Byte表示字节,1Byte=8bit 在问题中我故意没有写明确是GB还是Gb, 当然再仔细一想肯定是GB, 因为在计算机存储空间通常用Byte为单位, 在通信的传输速率上通常用bit为单位, 比如Gbps表示 Giga bit per second(千兆位每秒) , 每秒传输1G比特的信息(信息论的基本概念), 那么我们的问题更明确的问法应该是:

为什么32bit的系统最大内存空间为4GB?

  • 32位指的是一串32个01序列, 2的32次方个不同的序列, 每个序列代表一个内存地址, 一个内存地址有8bit也就是1Byte, 那么就有2的32次方个Byte, 4GB = 4*1024*1024*1024 = 2^32 Byte , 所以寻址范围大小为4GB

动态内存分配

对于数组而言, 必须指定数组的长度,数组的长度只有在运行时才知道,在定义数组的时候通常根据输入数据的个数来确定,但是很多时候输入数据的个数是不确定的, 这就需要我们按需供应内存空间, 也就是说在程序运行的过程中,某种数据类型(结构体,数组等)需要多少内存空间,就分配多少内存空间,这就是动态内存分配.

  • 动态内存分配注意事项:
    1. 不要忘记检查内存是否分配成功
    2. 在操作内存时, 是否超出了分配内存的边界
    3. 不要忘记释放内存空间, 这样可以使内存重新分配使用, 否则会引起内存泄漏, 释放后的内存不可再访问
    4. 在释放内存空间的时候, 不允许只释放内存的一部分, 动态分配的内存只能整块一起释放.

内存功能区

内存

如上图所示, 在内存条中,

  • 动态分配的内存是放在堆(Heap)中的, 随着分配的内存越来越多, 地址由低地址向高地址延伸的
  • 在程序运行时, 压栈所占用的内存是由高地址向低地址延伸的