C 和 C++ 指针简明学习笔记

C 语言中,指针存储的是变量的内存地址!!!

要彻底理解指针,首先要理解 C 语言中变量的存储本质,也就内存。

内存编址与内存空间

计算机的内存是一块用于存储数据的空间,由一系列连续的存储单元组成。
如下图所示,每个单元格都表示 1 个 bit,8 个 bit 为一组,称为 byte;byte 是计算机中作为内存寻址的最小单元
1 byte = 8 bit

图1

可以理解为,计算机给每个 byte 一个编号,这个编号就是内存的地址。
计算机中,每个 byte 的编号都是唯一的,从而保证了计算机可以通过每个编号访问到唯一确定的 byte。

图2

因为内存中,每个 byte 都有一个唯一的编号,所以编号的范围也就决定了计算机中可以寻址的内存空间。
所有编号连起来就是内存的地址空间。

变量存放

C++ 或 C 中可以如下定义向量

int a = 999;
char c = 'c';

当定义一个变量时,实际上是向内存申请了一块空间来存放变量(不同的数据类型,申请的空间是不同的)
int 类型占 4 个字节,在计算机中使用补码保存。
999 的补码为:0000 0011 1110 0111

图3

按照大端的存储方式,上述变量 a 会在内存中,如上图方式保存;如果是按照小端的存储方式,会如下图方式保存

图4

大端:高位字节放在内存的低地址的存储方式
小端:低位字节放在内存的低地址的存储方式

对于 float 、 char 、数组、指针、结构体、对象等类型的数据实际上也是一样的,需要先转换为补码,再按照大端或者小端的方式,依次将字节写入到内存单元中

指针

定义一个变量实际上就是向计算机申请了一块内存存放数据,这个地址可以通过运算符 & 得到(虚拟内存地址,并不是实际物理地址),得到的值就是变量所占内存块的起始地址,在 C 语言中通过 指针 这一概念来表示这个地址。

int * pa = &a;

pa 中存储的就是变量 a 的地址,也称为指向 a 的指针

所以,指针的本质,就是变量的内存首地址,即一个 int 类型的整数

那么问题来了,如果指针都是一个 int 类型的整数,为什么会有各种数据类型的指针呢?

pa 中存储的是变量 a 的内存地址,通过这个指针地址得到 a 的值的操作,称为 解引用*pa

由于指针存储的只是变量内存的首地址,对于不同变量,其所占内存空间是不同的,如果不能把所有数据从内存空间取出,那么解引用得到的数据就会出错,而指针的类型,则可以帮助编译器判断,从首地址开始取多少字节的数据,从而保证解引用的正确

图5

pa 指针本身也是一个变量,在内存中占有一定的空间

案例
float f = 1.0;
short c = *(short*)&f;

tu 6

从内存层面而言,f 没有发生任何变化
第二行代码,只是把 f 的前两个 byte 取出来,然后按照 short 指针的方式解引用,最后赋值给 c

那么,对于下面两行代码呢?

short c = 1;
float f = *(float*)&c;

(float*)&c 会让我们从 c 的首地址开始取四个字节,然后按照 float 的编码方式去解释
但是 c 语言 中 short 类型只占两个字节,那肯定会访问到相邻后面两个字节,这时候就发生了内存访问越界
当然,如果只是读,大概率是没问题的,但是,如果向这个区域写入新值

*(float*)&c = 1.0;

那么就可能发生 coredump,也就是访存失败
另外,就算是不会 coredump,这种也会破坏这块内存原有的值,因为很可能这是是其它变量的内存空间,而我们去覆盖了人家的内容,肯定会导致隐藏的 bug。

多级指针

多级指针,就是指针的指针的指针的指针…
实际上,多级指针只是一个为了方便我们理解和表达的逻辑概念

同样一个内存,如果存放的是别的变量的地址,就是指针;如果存放的是实际内容,就是变量;当存放的是别的指针的地址,就是指针的指针,依此类推,可以得到任意多级指针

指针本身也是一个变量,需要内存取存储,指针也有自己的地址
指针内存存储的是它所指向变量的地址

int a;
int *pa = &a;   // 指针
int **ppa = &pa;  // 二级指针
int ***pppa = &ppa;  // 三级指针

图7

如上图所示,pppa 就是三级指针,ppa 就是二级指针,pa 就是指针

对于 int ** a 可以把它分为两部分看,int **a*a 表示 a 是一个指针变量,int* 则表示 a 存放的是 int * 型变量的地址,对于其他多级指针都可以如此类推

  • 20
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值