C语言指针难吗?纸老虎而已,纯干货讲解( 二 )

C语言指针难吗?纸老虎而已,纯干货讲解
文章插图
 
在我个人的理解中,可以将指针理解成int整型,只不过它存放的数据是内存地址,而不是普通数据,我们通过这个地址值进行数据的访问,假设它的是p,意思就是该数据存放位置为内存的第p个字节 。
当然,我们不能像对int类型的数据那样进行各种加减乘除操作,这是编译器不允许的,因为这样错是非常危险的!
图2就是对指针的描述,指针的值是数据存放地址,因此,我们说,指针指向数据的存放位置 。
 

C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
指针的长度
我们使用这样的方式来定义一个指针:
Type *p;
我们说p是指向type类型的指针,type可以是任意类型,除了可以是char,short, int, long等基本类型外,还可以是指针类型,例如int *, int **, 或者更多级的指针,也可是是结构体,类或者函数等 。于是,我们说:
int * 是指向int类型的指针;
int **,也即(int *) *,是指向int *类型的指针,也就是指向指针的指针;
int ***,也即(int **) *,是指向int**类型的指针,也就是指向指针的指针的指针;
…我想你应该懂了
struct xxx *,是指向struct xxx类型的指针;
其实,说这么多,只是希望大家在看到指针的时候,不要被int ***这样的东西吓到,就像前面说的,指针就是指向某种类型的指针,我们只看最后一个*号,前面的只不过是type类型罢了 。
细心一点的人应该发现了,在“什么是指针”这一小节当中,已经表明了:指针的长度跟CPU的位数相等,大部分的CPU是32位的,因此我们说,指针的长度是32bit,也就是4个字节!注意:任意指针的长度都是4个字节,不管是什么指针!(当然64位机自己去测一下,应该是8个字节吧 。。。)
于是:
Type *p;izeof(p)的值是4,Type可以是任意类型,char,int, long, struct, class, int **…
以后大家看到什么sizeof(char*), sizeof(int *),sizeof(xxx *),不要理会,统统写4,只要是指针,长度就是4个字节,绝对不要被type类型迷惑!
为什么程序中的数据会有自己的地址?
弄清这个问题我们需要从操作系统的角度去认知内存 。
电脑维修师傅眼中的内存是这样的:内存在物理上是由一组DRAM芯片组成的 。
 
C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
而作为一个程序员,我们不需要了解内存的物理结构,操作系统将RAM等硬件和软件结合起来,给程序员提供的一种对内存使用的抽象 。
这种抽象机制使得程序使用的是虚拟存储器,而不是直接操作和使用真实存在的物理存储器 。
所有的虚拟地址形成的集合就是虚拟地址空间 。
 
C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
在程序员眼中的内存应该是下面这样的 。
 
C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
也就是说,内存是一个很大的,线性的字节数组(平坦寻址) 。每一个字节都是固定的大小,由8个二进制位组成 。
最关键的是,每一个字节都有一个唯一的编号,编号从0开始,一直到最后一个字节 。
如上图中,这是一个256M的内存,他一共有256x1024x1024 = 268435456个字节,那么它的地址范围就是 0 ~268435455。
由于内存中的每一个字节都有一个唯一的编号 。
因此,在程序中使用的变量,常量,甚至数函数等数据,当他们被载入到内存中后,都有自己唯一的一个编号,这个编号就是这个数据的地址 。
指针就是这样形成的 。
下面用代码说明
#include <stdio.h>int main(void){ char ch = 'a'; int num = 97; printf("ch 的地址:%p",&ch); //ch 的地址:0028FF47 printf("num的地址:%p",&num); //num的地址:0028FF40 return 0;}
C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
指针的值实质是内存单元(即字节)的编号,所以指针单独从数值上看,也是整数,他们一般用16进制表示 。
指针的值(虚拟地址值)使用一个机器字的大小来存储 。
也就是说,对于一个机器字为w位的电脑而言,它的虚拟地址空间是0~2w - 1 ,程序最多能访问2w个字节 。
这就是为什么xp这种32位系统最大支持4GB内存的原因了 。
我们可以大致画出变量ch和num在内存模型中的存储 。(假设 char占1个字节,int占4字节)


推荐阅读