一篇文章,初步理解指针

本文是对指针大部分内容的初步理解,帮助更好地学习指针。

目录

一.指针是什么

二.1.指针变量

二.2.不同类型的指针变量的差别

二.3.如何解引用指针变量

二.4.指针运算

 二.5.const修饰指针

 三.void*指针和野指针

四.二级指针

 五.指针数组

1.概念

2.指针数组的创建及初始化

3.指针数组模拟二维数组

4.数组读取元素的底层逻辑

4.1一维数组

4.2二维数组

六.数组指针变量和函数指针变量

六.1数组指针变量

 六.2函数指针变量



一.指针是什么

1.计算机上 CPU (中央处理器)在 处理数据 的时候,需要的数据是在 内存 中读取的,处理后的
数据也会放回 内存
2.管理内存时,我们把内存分为划分为一个个的内存单元,每个内存单元的大小是一个字节
--------------------------------------------------------
bit - ⽐特位    
Byte - 字节     1B yte = 8b it
KB                  1 KB = 1024B yte
MB                1 MB = 1024 KB
GB                1 GB = 1024 MB
TB                  1 TB = 1024 GB
PB                  1 PB = 1024 TB
---------------------------------------------------------
3.每个内存单元都有它自己的存放地址,在c语言中 指针就是 地址,地址 == 指针
4.32位CPU访问内存空间时,需要根据地址总线发出的地址信息来确定地址,32位机器有32根地址总线,64位机器有64根, 每根线只有两态,表⽰0,1【电脉冲有⽆】,因此 32位机器 地址大小 为32个bit位,也就是 4个字节 ,而 64位机器 中, 地址大小 为64个比特位,也就是 8个字节

二.1.指针变量

1.整形变量是存放整形的变量,字符变量是存放字符的变量,那么指针变量就是存放指针,也就是存放地址的变量

2.那么,怎么找到一个内容的地址呢?可以使用&取地址操作符

32位环境中,000000AEE9F2FA74就是a所在的地址

3.如何用指针变量存放地址呢?

int表示存放的地址所指向的内容的类型是整形,*p表示p是一个指针变量,专门用来存放指针的。

指针变量的一般创建形式就是 (地址所指向内容的数据类型) *(指针变量名)=(地址)

二.2.不同类型的指针变量的差别

得到地址后,计算机读取所需内容还需要所读取的长度,单位是字节,比如说

创建一个整形变量 初始化为10,在调试过程中,输入a的地址,发现a存放在内存中的是

0a 00 00 00(16进制中a为10,b为11.......),因为a的数据类型为int,所以a的内容存放需要四个字节,那么读取a时就需要一次读取4个字节,才能将a的内容读取完全,用·int*存放a的地址,因为int的大小是四个字节,在解引用时,就会一次读取四个字节,保证全部读取,同理,用char*存放时,一次只会读取一个字节(一个字节是8个bit位,也就是8个二进制数字,把2进制数字用16进制数字来表示时,一个16进制数字可以表示4个2进制数字,所以一个字节会用2个16进制数字来表达)

可以看到,a在内存中存放的内容为39 30 00 00,用int*来存放指针时,一次读取四个字节,打印出的内容和a本身一样,但是用char*存放指针时,一次只能读取一个字节,只读取了39,换算成十进制也就是57,所以,不同类型的指针变量的差别就是读取内容的长度地址加减的长度

(解引用和地址加减还没讲到,为了内容连贯先拿出来提及一下,后续会讲)

二.3.如何解引用指针变量

有了地址之后,我们可以通过   *   (  解引用)地址 来找到地址中所存放的内容

上⾯代码中就使⽤了解引⽤操作符, *p  的意思就是通过p中存放的地址,找到指向的空间,
*p其实就是a变量了;所以*pa = 0,这个操作符是把a改成了0.

二.4.指针运算

1.指针加减整数

上面我们提到的不同类型的指针变量的差别就是读取内容的长度地址加减的长度,这里我们运用数组来举例

int*类型的指针每次加减是 加减数*4 个字节 (也就是int类型的大小)

char*类型的指针每次加减是 加减数*1 个字节 

在数组中,数组的内容是连续存放的地址由低到高,所以,可以利用*(指针+数组下标)的方式读取数组的内容

2.指针减指针

p为数组首元素地址,p2为数组最后一个元素的地址,p需要加4次1才能到达p2,所以p2-p=4

也就是,用数组末元素地址-数组首元素地址=数组元素个数-1

 二.5.const修饰指针

变量是可以修改的,如果把变量的地址交给⼀个指针变量,通过指针变量的也可以修改这个变量。

但是如果我们希望⼀个变量加上⼀些限制,不能被修改,怎么做呢?这就是const的作⽤。

 

 

不用const修饰*p时,*p是可修改的,const修饰*p表示p指向的对象不可通过*p修改,所以修饰后再用*p修改就会报错

const的使用方式:

1.const修饰*p(地址指向的对象),对象不可通过*p修改,但是可以直接通过变量名修改

格式:const int * p   或  int const * p(只要保证const在*p前面即可)

 

 2.const修饰p(地址),地址不可通过p再改变

格式:int* const p

 

 上述中p指代地址,*p指代地址指向的对象,int为对象的数据类型

 三.void*指针和野指针

1.void*指针:在指针类型中有⼀种特殊的类型是 void * 类型的,可以理解为⽆具体类型的指针(或者叫泛型指
针),这种类型的指针可以⽤来接受任意类型地址。但是也有局限性, void* 类型的指针不能直接进
⾏指针的+-整数和解引⽤的运算

2.野指针:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

此文章中不再详细解释野指针及void*指针

四.二级指针
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪⾥?
这就是 ⼆级指针 。

可以看到p1存放的地址就是p所在的地址,这就是二级指针。

那么如何使用二级指针呢?常见的使用方法通常是二次解引用。

*

 p1存放的是p的地址,*p就是读取p所在地址的内容,也就是a所在的地址

那么**p,就是解引用a所在地址的内容,也就是读取变量a了。

 五.指针数组

1.概念

我们常见的有 int arr【】整形数组,char arr【】字符数组,那么指针也会有数组,由指针组成的数组就叫做指针数组

2.指针数组的创建及初始化

我们经常使用的整形数组,比如 int arr[10]

表示创建一个10个元素的数组,每个元素的数据类型都是 int 类型。

那么同理

int* p[3]就是创建了一个3个元素的数组,每个元素的数据类型都是 int*

 在所示代码中,都创建了3个元素的指针数组,只是解引用的方式不同,这涉及到数组的底层逻辑,会在后续提到。

3.指针数组模拟二维数组

 

 将3个数组的首元素地址依次放入指针数组p中,因为数组中元素都是由低到高连续存放的,所以, 地址首元素+地址下标  就可以找到数组中该下标的元素的地址,再解引用,就可以读取其内容。

读取内容时,我们使用的是p[i][j]的方法,类似于二维数组。

4.数组读取元素的底层逻辑

 

4.1一维数组

arr1[1]读取的是数组中的第二个元素,也就是2

arr1是数组首元素的地址,arr1+1,就是数组第二个元素的地址,那么*第二个元素的地址,也可以找到第二个元素

在底层逻辑中arr1[i]在运行过程中就会变成*(arr+1),这就是数组读取元素的底层逻辑

所以 arr1[1]==*(arr+1)

4.2二维数组

 

首先,我们要知道,二维数组就是一维数组的数组,二维素组的每个元素都是一维数组,

arr[2][3]可以看作由2个元素组成,每个元素都是由3个元素组成的数组。

 比如,在二维数组中,arr[1][2]读取数组中第二行,第三个元素。

在上述代码中,底层逻辑是先  *(arr+1),arr是二维数组数组名,也就是首元素地址,等价于第一个数组的地址,

所以,+1得到第二个数组的地址,等价于&arr[1],那么第一次解引用,*和&抵消,相当于得到第二个数组的数组名,也就是第二个数组首元素地址,再次解引用就可以访问第二个数组的元素。

由此也可以得到,二维数组传参的本质就是传递首个一维数组的地址。

六.数组指针变量和函数指针变量
六.1数组指针变量

 1.数组指针变量就是存放数组地址的变量

2.数组指针变量的写法 格式 :数组元素数据类型(*变量名)[元素个数]=&元素名

比如

解释:p先和*结合,说明p是⼀个指针变量,然后指针指向的是⼀个⼤⼩为3个整型的数组。所以p是 ⼀个指针,指向⼀个数组,叫 数组指针。
这⾥要注意:[]的优先级要⾼于*号的,所以必须加上()来保证p先和*结合。
 六.2函数指针变量

 1.函数也有自己的地址,函数指针变量就是存放函数地址的变量

2.函数指针变量的写法

 3.函数指针变量的使用

 通过函数指针调⽤指针指向的函数,在这里,print==&print,p==(*p)

 

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值