C语言——深入理解指针(1)

目录

1.内存和地址

a 内存的理解 

b 如何理解编址 

2.指针变量和地址

  a 取地址操作符

b 指针变量  

c 解引用操作符 

d 指针变量的大小 


 

1.内存和地址

a 内存的理解 

        假想这样一个场景,你的朋友找你玩,到了你家小区,如何让她迅速的找到你家呢?当然有很多方法,最直接有效的方法是你告诉她你家在几栋几号,这样就可以通过编号来迅速找到你。此时几栋几号就是你的地址。

        当然,计算机CPU在处理数据的时候,需要的数据是在内存中读取的,处理后的数 据也会放回内存中,那么如何高效简洁的管理空间呢?其实也是把内存划分为⼀个个的内存单元,每个内存单元的大小取1个字节。

        当然,需要我们了解一下计算机的进制转换,

       1字节(byte)= 8比特(bit);比特是计算机中的最小内存单位

       1KB =1024字节;      1MB=1024KB 

       1GB = 1024 MB;      1TB=1024GB

C语言——深入理解指针(1)_第1张图片

b 如何理解编址 

        CPU访问内存中的某个字节空间,必须知道这个字节空间在内存的什么位置,而因为内存中字节很多,所以需要给内存进行编址(就如同宿舍很 多,需要给宿舍编号⼀样)。 计算机中的编址,并不是把每个字节的地址记录下来,而是通过硬件设计完成的。 正如钢琴、吉他上面没有写上“都瑞咪发嗦啦”这样的信息,但演奏者照样能够准确找到每⼀个琴弦的每⼀个位置,这是因为制造商已经在乐器硬件层面上设计好了,并且所有的演奏者都知道。本质是⼀种约定出来的共识!

        首先要明白计算机有很多硬件,这些硬件不完全相同,但是要分工协作共同完成工作,那么怎么能实现这个功能呢?那就更简单了,就是用线将它们连接起来。而我们真正需要注意的一个线叫做地址总线,可以这么理解,32位的计算器有32条这样的线,每个线有两种状态,分别是0和1,那么32根线一共能表示2^32种状态,这样的每个状态就是我们的一个地址,他们分别储存在不同的硬件上,地址信息被下达给内存,在内存上,就可以找到该地址对应的数据,将数据在通过数据总线传入CPU内寄存器。

        简单的说,内存单元的编号==地址

        一句话简明的说,地址就是指针,内存单元的编号  ==  地址  ==  指针

2.指针变量和地址

  a 取地址操作符

在c语言中,我们创建一个变量的实质就是向内存申请一块空间 ,举个例子,我们创建一个变量a

int a = 10;//这个实质是向内存申请4个空间来存放a的数值

就是这个东西,每一个字节有一个编号 

C语言——深入理解指针(1)_第2张图片

 

那我们如何获取a的地址呢?,这里就要用到取地址符号了& 

取地址符号是单目操作符号,我们之前

结合我们常使用的打印数字来说明 

#include 
int main()
{
	int a = 10;
	printf("%d", &a);

	return 0;
}

这里这个取地址符号就取出a中较小地址,进行打印处理

我们这里用%p打印处理看看 

 

C语言——深入理解指针(1)_第3张图片

虽然我们这里是较小的地址,但是是不是可以顺藤摸瓜我们直接获取其他地址啊,其实不同类型的指针的权限是不同的,这里我们后边说

好了,上边的这个&a其实就是一个指针变量,那么我们P=&a的话,这个P就是指针变量

b 指针变量  

        那我们通过取地址操作符(&)拿到的地址是⼀个数值,比如:0x006FFD70,这个数值有时候也是需要存储起来,方便后期再使用的,那我们把这样的地址值存放在哪里呢?答案是:指针变量中。

        那么指针变量我们怎么表示呢?在c语言里用以下表示

int* pa = &a;

 如何拆解指针类型?C语言——深入理解指针(1)_第4张图片

 

OK,下面我们来看看这个该怎么写

char ch = ‘m’;
pc = &ch;//pc的类型怎么写

好滴,聪明的我已经知道了要用char*了,哈哈哈哈 

c 解引用操作符 

        我们将地址保存起来,未来是要使用的,那怎么使用呢? 在现实生活中,我们可以通过仓库编号直接去拿放东西,C语言中其实也是⼀样的,我们只要拿到了地址(指针),就可以通过地址(指针)找到地址(指针)指向的对象,这里必须学习⼀个操作符叫解引用操作符(*)。 

#include 
int main()
{
	int a = 10;
	
	int* pa = &a;
	*pa = 0;//解引用符号应用
    
    return 0;
}

上述代码中的*pa就是解引用操作符,它的作用是通过pa的地址来找到对应地址的值,所以说*pa其实就是a,我们可以通过打印a,和*pa来进行验证 

#define _CRT_SECURE_NO_WARNINGS
#include 
int main()
{
	int a = 10;
	
	int* pa = &a;
	*pa = 0;

	printf("a=%d\n", a);
	printf("*pa=%d\n", *pa);

		

	return 0;
}

从而我们得到

 

其实取地址操作符&和解引用操作符*在一定程度上是互逆的,我们可以这样写

int a = 10;
*&a = 0;

然后我们可以看到结果

C语言——深入理解指针(1)_第5张图片 

 

到了这里,有些同学会疑惑,既然我们通过了一个指针变量使a变为0,那为何不直接把a赋值为0,而要绕一圈子里?

其实这里就是将a交给pa来处理的,多一种处理方式。举个例子,就是有些大官看不惯一个人,他不好自己出手,就交给自己的小弟出手来解决,这种感觉,随着指针的学习,会越来越理解。

d 指针变量的大小 

        说来说去,指针就是内存变量,既然是变量,就会有他的大小,要想知道指针变量的大小,我们还要从内存说起。我们已经知道,32内存位计算器有32条地址总线,每条线有1和0两个状态,那么一个内存的编号就有32条地址线表示,一条地址线占一个比特位,那么32条地址线就是32个比特位,因此就是4个字节。同理,64位计算机的话,就是8个字节。我们可以通过sizeof函数来进行验证,验证代码如下

#define _crt_secure_no_warnings
#include 
int main()
{
	printf("%zd\n", sizeof(char*));
	printf("%zd\n", sizeof(short*));
	printf("%zd\n", sizeof(int*));
	printf("%zd\n", sizeof(float*));
	printf("%zd\n", sizeof(long*));


	return 0;
}

我们首先在x86环境里验证

C语言——深入理解指针(1)_第6张图片 

可以发现无论哪个类型的指针变量的大小都是4。

然后我们在x64环境里进行验证

C语言——深入理解指针(1)_第7张图片 

发现每个指针变量的大小都是8个字节。

上边的验证也很好的说明了指针就是内存,32位系统一个内存是4个字节,因而其指针变量大小也是4个字节。64位系统一个内存是8个字节,因而指针变量大小也是8个字节。 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(c语言,开发语言)