C语言指针

一、C语言基础变量的定义

首先,C语言变量定义的基本形式: <变量类型> <变量名称>

变量类型,就是确定了变量名称对应的实体是什么?比如

int a;   //变量a是一个整型数
char b;   //变量b是一个字符

现实生活也有<变量类型> <变量名称>这样的形式,比如,有一个名称angle,那angle是什么?一个人?一个物品?加上对angle的类型描述后,那就确定了angle的对象属性。

女人 angle;   //angle是一个女人
物品 angle;   // angle是一个物品

在这里插入图片描述

二、C语言指针的定义

理解了C语言基础变量定义的概念后,我们再来对应理解C语言指针的定义,指针也是一种变量,也符合变量定义的基本形式:
<变量类型><变量名称>

int  *p;

很多人对指针不理解或者理解不透彻,有两个方面的原因:

1.被指针这个翻译/叫法带偏了。
2.定义指针变量时,被这个*习惯性地用法/写法带偏了

1.指针是一种变量,它的变量类型(变量实体)是一个地址,咱们把“指针”改成“地址变量”,以后碰到指针,就叫做“地址变量”,也就是说这个变量的实体内容是一个地址。

2.定义一个指针变量,习惯性写法是把*靠近变量名,按照C语言变量定义的基本形式<变量类型> <变量名称>,很容易产生错误的理解。那么咱们换一个写法,把*往前写,远离变量名,来看看效果。
以一个整型指针变量的定义为例,画个表格对比两种写法,帮助理解。
在这里插入图片描述以上表格可以清晰的看出,在变量定义时,是一种变量类型,表明变量是一个指针类型的变量,也就前面说的地址变量。但是,在变量定义时,需要和其他基础变量类型一起使用,组成意义更具体的变量类型,比如,int 和一起使用,

int* p;

同样,以表格的形式来帮助理解
在这里插入图片描述在这里插入图片描述

三、C语言指针的用途

现在理解了指针的定义以及指针就是一个地址变量,那么指针或者叫做地址变量在C语言里面具体代表什么?有什么用途呢?

在计算机的世界里,万事万物皆信息,信息都需要存储空间,存储空间都有地址
类似现实生活中每个人都有居住空间和居住空间的地址,xx省xx市xx区xx街道xx小区xx楼xx单元xx号。
计算机世界的地址没那么复杂,就是一个简单整形数,比如,0x0000 0004,0x8000 0000等等,地址是多少字节是编译器根据计算机体系结构确定的,这个内容后续章节再讲解。
下面我们以实际的程序来讲解,

int a ;
int b ;
int *p;

a、b、p都是变量,编译链接后或者运行时,就会分配一个存储空间,具体会分配到哪个地址是由编译链接时和运行时确定,暂且先不管,比如分配如下:
在这里插入图片描述
这个时候变量 a、b、p都被分配了自己的存储空间和对应的空间地址,但是,存储空间没有指定存储什么内容,一般默认0或者是随机值,这个后续再深入讲解。现在可以理解成什么都没有存,是空的。
现在对a、b、p空间写内容,在C语言中称之为赋值

a = 10;
b = 20;

在这里插入图片描述
很简单,对不对,赋值后就成为上图所示。**但这个时候p还是一个空的,我们称之为空指针。**接下来,有小伙伴按耐不住了,给p指针也赋值呗,通过前面的介绍,p指针也称之为地址变量,它的内容应该是一个地址,那么,我们把a变量的地址,赋值给p指针,有小伙伴可能这么写了,

*p = 0x2000;

一运行程序,就崩溃了,为啥?为啥!说明之前对于指针定义的理解,还是错误的。那我们把之前对指针的定义,再般过来,认认真真看一遍。
在这里插入图片描述p才是真正意义的指针变量,在指针定义的时候,是指针变量的类型。类似,我们不能已经定义了变量a后,给a赋值时,再带上变量类型,就是错误的了。

int a = 10// 错误的写法

同理,指针变量的赋值,也不能带上*变量类型,

p = 0x2000// 这样就对了。

可能有很多小伙伴,就不服气了,经常在代码里面见到,指针变量*p = 0x2000;的这种写法啊,这个咱们后续文章讲解指针操作的时候在详细讲解。

按照上面的步骤给指针变量赋值后,指针的地址是0x1000,指针的内容是0x2000,地址变量p的地址是0x1000,地址变量的值是0x2000,这样指针p就指向了变量a,如下图。
在这里插入图片描述

四、C语言指针的操作符号

int *p;
*p=0x2000;  //错误的赋值,会导致程序崩溃或者跑飞  
p=0x2000;  //正确的赋值
int *p;      // 定义指针变量p 
p=0x2000;  // 对指针p赋值
*p=0x2000;  // 这里可以对*p赋值了

为什么经过改写后的程序就可以对p赋值了呢?这里就需要理解号在指针的定义和指针操作上的区别。

int *p;      // 定义指针变量p 
p=0x2000;  // 对指针p赋值
*p=0x2000;  // 这里可以对*p赋值了
*在指针定义时,是一种变量类型,表明变量是一个指针类型的变量

*在指针操作时,是一种指针运算/操作符,它代表指针所指向地址的值,或者说代表指针所指向地址的内容,又或者说代表指针所指向地址的对象。

类似现实生活中每个人都有居住空间和居住空间的地址,xx省xx市xx区xx街道xx小区xx楼xx单元xx号。指针p代表的是地址xx省xx市xx区xx街道xx小区xx楼xx单元xx号;*p代表的是地址xx省xx市xx区xx街道xx小区xx楼xx单元xx号所对应的房屋空间,地址是不能住人的,但地址对应的房屋空间是可以住人的。
在这里插入图片描述嵌入式底层驱动最常用就是对MCU、单片机的寄存器进行读写操作,而MCU、单片机的寄存器就是固定的地址,通过指针能够对地址直接读写操作,简单又效率高的特性,就是为什么嵌入式底层驱动都是C语言编程的主要原因,简直就是嵌入式底层驱动的设计的利器。

五、C语言指针的操作符*和&

在C语言中,&有三种作用,分别如下:

  1. 取地址操作符,单目运算符。用来取一个变量的地址。比如
int i, *p;
p = &i;  //这里的&作用是取变量i的地址
  1. 位与操作运算符,也就是常说的and操作,双目运算符。计算的时候按位计算,&两边操作数按位(bit)做与操作。比如,

0x12&0x23 转为二进制(bit)为:

B00010010&B00100011,按位计算结果为B00000010,即结果为0x02。

  1. 当两个&&一起用的时候,表示为逻辑与运算。

逻辑运算结果只有0和1两种结果。一般在&&两边是两个逻辑表达式。比如,

2>1 && 0<1 这个的值为1&&1 = 1。

1>2 && 2>0 这个值为0&&1 = 0。

1>2 && 2>3 这个值为0&&0=0
有了取地址符&,那么我们把之前程序改一下,同样也可以达到对变量a和b赋值操作。

修改前:

int *p;
p=0x2000// 第一步,将指针变量赋值成变量a的地址,指针p就指向了变量a
*p=10; // 第二步,对指针所指向的地址空间(就是变量a空间)进行赋值
p=0x3000; // 第三步,将指针变量赋值成b的地址,指针p就指向了变量b
*p=20; // 第四步,对指针所指向的地址空间(就是变量b空间)进行赋值



修改后

int *p,a,b;
p=&a; // 第一步,将指针变量赋值成变量a的地址,指针p就指向了变量a
*p=10; // 第二步,对指针所指向的地址空间(就是变量a空间)进行赋值
p=&b; // 第三步,将指针变量赋值成b的地址,指针p就指向了变量b
*p=20; // 第四步,对指针所指向的地址空间(就是变量b空间)进行赋值

这样心情是不是瞬间就舒畅多了。

上面程序中的p指针(地址变量),也有存储空间,那么对应的也有存储地址。p指针的地址同样也可以通过取p指针的地址来获得,也就是&p。

拓展一下,除了变量有地址,代码也有地址,变量对应的空间一般为堆或者栈数据空间(有些常量也可能放到代码空间),代码对应的是指令空间。函数调用,其实就是调用函数的入口代码的地址(指令),在汇编语言里面称之为call或者跳转。

假设,p、a、b变量的地址和内容,如下图示,
在这里插入图片描述
那么,再看看下面代码的意义

&p; // 指针(地址变量)p的地址0x1000
p;  // 指针(地址变量)p的值0x2000,是一个地址,也就是a的地址&a。
*p; // 指针(地址变量)p所指向的内容10,就是0x2000地址对应的值(对象),    
    // 也就是变量a所对应的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值