C语言指针:内存和指针

本文介绍了内存和地址在计算机中的作用,以及如何在C语言中通过指针操作内存。主要内容包括内存的作用、地址的定义、取地址操作、指针和指针变量的概念、解引用操作以及指针变量的大小与类型。
摘要由CSDN通过智能技术生成

一、内存和地址

1.内存

在计算机的组成结构中,有一个很重要的部分,就是存储器。存储器是用来存储程序和数据的部件,对于计算机来说,有了存储器,才有记忆功能,才能保证正常工作。存储器的种类很多,按其用途可分为主存储器和辅助存储器,主存储器又称内存储器(简称内存,港台称之为记忆体)。
内存又称主存,是CPU(中央处理器)能直接寻址的存储空间,由半导体器件制成。内存的特点是存取内存速率快。
内存就是暂时存储程序以及数据的地方

举一个例子:
假设有一栋宿舍楼,你的同学就住在这栋宿舍楼里面,如果有一天你想去找他玩,但这栋楼的房间都没有编号,你的同学也不好描述他所在的宿舍位置,你就只能挨个房间去找。
在这里插入图片描述如果这栋宿舍楼有100个房间,最坏的情况,你可能会找100次房间,才会找到你的同学。但是如果我们给宿舍楼里的每层每间房都编一个号,比如三层二号房302,六层十四号房614。这样你的同学提前告诉你他在614号房间,你就可以很快高效的找到你的同学。
计算机中内存也是像宿舍楼这样,将内存划分为一个个的内存单元,每个内存单元的大小取1个字节。计算机中常见内存单位的换算:
在这里插入图片描述每个内存单元就像一间学生宿舍一样,1个字节空间里有8个比特位,就好比一间宿舍住八个人一样。一个比特位上存储的是二进制的0或者1。
1字节

2.地址

每个内存单元也都有一个编号(这个编号就相当于宿舍房间的门牌号),有了这个内存单元的编号,CPU就可以快速找到一个内存空间。
在这里插入图片描述生活中我们把门牌号也叫地址,在计算机中我们把内存单元的编号也称为地址。C语言中给地址起了新的名字叫:指针。由上图,每个字节都对应着一个编号,也就是地址。
所以我们可以理解为:
内存单元的编号==地址==指针。
关于计算机中地址的深入学习,请点击下面的链接阅读。
https://blog.csdn.net/m0_62183318/article/details/137638845

二、认识指针

1.取地址

理解了内存和地址的关系,在C语言中创建变量其实就是向内存申请空间,例如:

#include<stdio.h>
int main()
{
	int n = 10;
	return 0;
}

在这里插入图片描述上述的代码就是创建了整型变量n,向内存申请了4个字节的空间,用于存放整数10,其中每个字节都有地址,上图中4个字节的地址分别是:

1 0x00D3F710
2 0x00D3F711
3 0x00D3F712
4 0x00D3F713

上面是如何得到变量n的地址的呢?这里要用到一个取地址操作符:&

#include<stdio.h>
int main()
{
	int n = 10;
	&n;//取出n的地址
	printf("%p\n", &n);
	return 0;
}

在这里插入图片描述这里是小端字节序存储,也就是这个整型变量的低位字节排放在内存的低地址端,后面会讲到这个知识点的。
由上面的代码,对变量n取地址,然后打印,会得到这个变量的地址为0x00D3F710(开头的0x表示十六进制),由此可知&n取出的是变量n所占4个字节中地址较小的字节的地址。虽然整型变量占4个字节,但是只要知道了第一个字节的地址,后面三个字节地址也就可以知道了,这样就能访问4个字节的数据了。

2.指针和指针变量

(1) 通过取地址操作符(&)拿到的地址是一个数值,比如上面n的地址00D3F710这个数值有时候也是需要被存储起来的,方便后期再使用,我们把这样的地址值存放在指针变量中。

#include<stdio.h>
int main()
{
	int n = 10;
	int* pn = &n;//取出n的地址并存储到指针变量pn中
	return 0;
}

只要记住,用来存放地址的变量就叫指针变量。通常我们叙述时会把指针变量简称为指针,但实际他们的含义不同:指针就是地址。但是我们单独说指针变量时,他是一个变量,其中存放的是其他变量的地址,他是可变的。通过上面的代码来说明:
1.指针— —即地址
比如上面的&n就是变量n的指针,一个变量的地址称为该变量的指针。通过变量的指针能够找到该变量
&n:n的地址或者叫n的指针
2.指针变量— —专门用于存储其他变量地址的变量
比如上面的指针变量pn的值就是变量n的地址,指针与指针变量的区别,就是变量值与变量的区别
假设上面得到n的地址为0x0118F704,则pn=0x0118F704
(2) 指针的类型
指针也是有类型的,那要如何理解指针的类型呢?就比如上面的int* pn = &n:

int n = 10;
int* pn = &n;

指针变量pn的左边是int*,其中*号是在说明pn是一个指针变量,前面的int是在说明pn指向的是整型(int)类型的对象。
假设这里得到n的地址为0x0118F704:
在这里插入图片描述所以这里pn的类型是int*,pn存储了n的地址,我们就说pn指向了n。上图中指针变量pn也是有自己的地址的,只是这里没有给出,后面讲二级指针时会说明的。
类似的,如果要存放一个字符类型变量的地址:

char ch = 'q';
char* pc = &ch;

指针变量前的*号不管是挨着类型名、挨着变量名或是单独空出来都没有影响,都是一样的意思。
在这里插入图片描述

3.解引用操作符

我们将地址保存起来,未来是要使用的,那要怎么使用呢?
在现实生活中,我们使用地址要找到一个房间,在房间里可以拿去或者存放物品。
C语言中其实也是一样的,我们只要拿到了地址(指针),就可以通过地址(指针)找到地址(指针)指向的对象,这里要学习一个操作符叫解引用操作符(*)

#include<stdio.h>
int main()
{
	int n = 10;
	int* pn = &n;
	*pn = 20;
	return 0;
}

上面的代码中*pn = 20;就使用了解引用操作符,*pn的意思就是通过pn中存放的地址,找到指向的空间,*pn就等价于变量n了;所以*pn = 20,就是把n的值改成了20。
那为什么不直接对n赋值改掉n的值,而要通过指针解引用来赋值呢?其实这样就多了一种修改变量值的途径,写代码就会更加的灵活。后面在学习函数传址时会深入理解这里的知识。

4.指针变量的大小

(1) 因为指针变量是用来存储地址的,所以指针变量的大小取决于地址的大小。
通过上面对计算机中地址的深入学习可知,在32位机器下,假设有32根地址总线,每根地址线出来的电信号转换成数字信号后是1或0,那我们把32根地址线产生的2进制序列当做一个地址,那么一个地址就是32个bit位,8个bit位为一个字节,需要4个字节才能存储。
如果用指针变量来存放地址,那么指针变量的大小就得是4个字节的空间才可以。
同理在64位机器下,假设有64根地址线,一个地址就是64个二进制位组成的二进制序列,存储起来就需要8个字节的空间,指针变量的大小就是8个字节。

#include<stdio.h>
int main()
{
    //32位平台下地址是32个bit位(即4个字节)
    //64位平台下地址是64个bit位(即8个字节)
	printf("%zd\n", sizeof(char *));
	printf("%zd\n", sizeof(short *));
	printf("%zd\n", sizeof(int *));
	printf("%zd", sizeof(double *));
	return 0;
}

在这里插入图片描述上面的代码在32位平台下运行结果:
在这里插入图片描述上面的代码在64位平台下运行结果:
在这里插入图片描述总结:
32位平台下地址是32个bit位,指针变量大小是4个字节
64位平台下地址是64个bit位,指针变量大小是8个字节
指针变量的大小和类型是无关的,只要是指针类型的变量,在相同的平台下,大小都是相同的。

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

米饭「」

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值