从0开始认识指针,再到熟悉基本的运用(1)

全文可能会太长,建议分开“食用”


1、指针到底是什么

1、1内存和地址

其实指针也叫做内存,同时,指针也可以叫做地址。
上面的话翻译过来,也就是指针=地址=内存
当然在计算机语言中,不能忘记,==才是正常等号的意思。
那么,话又说回来,看到这里,一定会有人会想知道,我连指针是什么都不知道,现在又来了,什么内存啊,什么地址,那这些又是什么呢。所以接下来,我们要先讲一下内存和地址。

1、1、1内存

其实形象一点的概括的话,内存也就相当于是一个在现实生活中的学生宿舍,而我们购买的电脑上面内存有8GB/16GB/32GB就相当于是公寓的大小。那么那么大的公寓里面或者说是内存,我们应该怎么样高效的管理呢?带着这样的疑问。更进一步的话,我们可以了解到,内存之中还会有内存单元,也就相当于是宿舍里面的一间间宿舍一样,而每一个内存单元也就是一个字节的大小,能存放8个比特位,也就好比是一个宿舍里面住了8个同学一样。如此细致的话,不难想像如果是要找到在一个楼里面的一个同学,就不会一间房间,一间房间的找了,从而实现高效的处理数据。

1、1、2地址

在现实中的门牌号,也就相当于是地址,在计算机中,我们也把内存单元的编号叫做地址。而在c语言中,我们给地址取了一个新的名字:指针。
所以,我们会说指针=地址=内存单元的编号
在这里插入图片描述

2、编址又是什么

2、1基本的理解

其实编址就相当于是门牌号。CPU就像宿管一样,宿管想要找到一位同学,必须知道在什么位置,而又因为,宿舍楼里面会有很多的人,所以就需要宿舍编号,从而让CPU能更高效的找到内存中存储数据的位置,所以就产生了编址。
计算机中的编址,并不是把每个字节的地址记录下来,而是通过硬件设计完成的。如果看不懂的话,可以从现实中找些案例,就比如说乐器,钢琴,吉他等。上面都没有写“do、re、mi、fa、sol、la、si ”**这样的信息,但是演奏者都能照样找到自己需要的音调,这是为什么呢?这就是制造乐器的时候,已经设计好了,并且演凑者都已经知道的。本质是一种约定的共识!在硬件上设计的硬件的编址也是如此

2、2更深入的了解

首先,必须知道的是,计算机里面有很多的硬件单元,而硬件但愿是要相互协同工作的。所谓的协同合作,至少要是相互之间,能够进行数据传递。但是硬件与硬件之间是相互独立的,那么又是怎么连接起来的呢?其实,答案很简单,就是用“线”。
在这里插入图片描述
CPU和内存之间,有着大量的数据交互,所以,两者之间也存在着很多连结着彼此的线。虽然上图中有着三大类(地址总线,数据总线,控制总线)。但是今天只关心一组线,叫做地址总线
简单点理解,32位的机器有32根地址总线,每根只有两态,表示0,1(电脉冲的有无),那么每一根线就会有两种含义,两根线就是4种,以此类推,一个32位的机器,就能表达出2^32种含义,每一种都能代表一个地址。
这样地址信息下达给内存,在内存上,就可以找到该地址的对应的数据,将数据再通过数据总线传入CPU寄存器。

3、指针变量和地址

3、1取地址操作符(&)

了解了内存和地址的关系后,再看回C语言,在C语言中创建变量其实就是在向内存申请空间,比如:在这里插入图片描述
在这里,我们创建了整型变量a,内存中申请4个字节,用于存放整数10,其中每个字节都是有地址的,上图的4个字节的地址分别是:在这里插入图片描述
那么,在正常的情况下,我们怎么获得a的地址呢?
这下,我们就需要用到一个操作符==&==。接下来用这个操作符来尝试一下。

#include <stdio.h>
int main()
{
   int a=0;
   &a;
   printf("%p\n",&a);
   return 0;
   }

当在操作系统中执行后,会打印处理:006FFD70。&a取出的是仅仅是a所占4个字节中较小的字节中的地址。虽然是只知道第一个地址,但是我们也可以顺藤摸瓜的找到其他3个地址。

4、指针变量和解引用操作符(*)

4、1指针变量

通过上面的取地址操作符(&)取出的a的地址,这个数据我们也是需要贮存起来的,从而为了后期方便使用,那么我们把**地址值存储在哪里呢?**那当然就是指针变量之中了。

#include <stdio.h>
int main()
{
   int a=10;
   int *p=&a;//这里就是把取出a的地址,然后把他存储在指针变量p中。
   return 0;
 }

指针变量也是一种变量,这种变量是用来存放地址的,存放在指针变量中的值,都会被理解为地址

4、1、1更全面的理解指针变量

在上面一个代码中,我们能看到一个新鲜的类型

int a=10;
int *p=&a;

其中p,边上写的是int*,而*的意思就是在说明p是指针变量,而前面的int是在说明p指向的是整型(int)类型的对象。
在这里插入图片描述
那么由此来看,如果是char类型的变量ch,ch的地址,要存放在什么类型的执政变量中呢?

char ch='w';
char *p1=ch;

4、1、2指针变量的大小

在前面我们提到过,32位机器假设有32根地址总线,每根地址线出来之后的电信号转化为数字信号后就是1或者是0,那么32根地址线产生的2进制序列当作一个地址,那么一个地址就是32个bit位,需要4个字节才能储存。
1byte = 8bit
1KB = 1024byte
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
1PB = 1024TB

bit比特,byte字节
同理,还有64位的机器,那么他的一个地址就应该是存储需要8个字节的空间,指针变量的大小就是8个字节。当然,我们也可以通过在程序里面来直接展示出指针变量不同类型的大小。就比如下面这一段代码,自己之后运行一下,就能观察到不同的大小了。

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

注意:指针变量的大小和类型是无关的,只要是指针类型的变量,在相同的平台下 ,大小就是相同的
所以上面写出来的代码的结果就是
在这里插入图片描述

4、2解引用操作符(*)

如果我们将地址保存起来后,以后要使用,那么我们应该怎么办呢?其实,在C语言中,我们只需要拿到地址(指针),就可以通过地址(指针)找到地址(指针)指向的对象,这里就必须用到一个至关重要的操作符,叫做解引用操作符(*)。

1 #include <stdio.h>
int main()
{
 int a = 100;
 int* pa = &a;
 *pa = 0;
 return 0;
}

此处,我们就使用解引用操作符,*pa的意思就是通过存放的地址,找到对应指向的空间,*pa就已经是a变量的意思了,所以上述操作,也就是把a改成了0。
那么,我们为什么要用到指针,还要用到解引用操作符呢,为什么不用直接a=0。其实这里的地方是可以直接用a=0的,但是这种方法也是多了一种途径,并且在下面学会了更深入的了解和运用,我们将会发现这里的作用是不可或缺的。

5、指针变量类型的意义

5、1指针的解引用

可以通过下面这两段代码,来开始了解

//代码1
#include <stdio.h>
int main()
{
 int n = 0x11223344;
 int *pi = &n;
 *pi = 0;
 return 0;
}
//代码2
#include <stdio.h>
int main()
{
 int n = 0x11223344;
 char *pc = (char *)&n;
 *pc = 0;
 return 0;
}

其实,对于刚刚学习的我们来说,这感觉其实差不多,不一样的只是,指针类型的不同。可是我们运行完之后发现。代码1会将n的4个字节全部改为0,而代码2只能将n的第一个字节改为0。
所以,我们大概也能知道,从中找到一些规律。就比如,char的指针,解引用就只能访问一个字节,而int的指针的解引用就能访问4个字节。
结论:指针的类型能决定对指针解引用的时候,能有多大的权限(也就是一次能放访问几个字节)

5、2指针+,- 整数

由一段代码引入

#include <stdio.h>
int main()
{
 int n = 10;
 char *pc = (char*)&n;
 int *pi = &n;
 
 printf("%p\n", &n);
 printf("%p\n", pc);
 printf("%p\n", pc+1);
 printf("%p\n", pi);
 printf("%p\n", pi+1);
 return 0;
}

结果
可以看出,char类型的指针变量+1跳过的是1个字节,int类型的指针变量+1跳过的是4个字节。这就是指针变量不同类型带来的差异性变化。


预知下回如何,待我军训完,继续编辑。后面还有const修饰指针变量等更多精彩刺激的内容。希望都不要落下哦。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值