C语言指针详解(基础知识、字符指针、数组指针)

一.指针变量的基础知识

1.1指针变量的概念 —— 取地址操作符( & )

在探讨什么是指针之前我们先想一个现实中的情况,假如你的同学邀请你去他的寝室,你一定需要提前问他的寝室号是多少

而指针变量相当于内存中的寝室号,它保存的是每个变量/函数/数组等的地址

注:我们常说的指针其实是指针变量,指针实际上是一个地址(即寝室号)

取地址操作符( & ) 可以理解为找你同学要他的寝室号这个行为

在内存中,& 后面加 变量/函数/数组 代表  变量/函数/数组  的地址

例如:

图1.1

图中 000000000062FE1C 就是 变量 a 的地址(房间号)

1.2指针变量的定义

在图1.1中,我们打印了 a 的地址,是通过 &a 这样取地址的行为(即你向你同学问他的寝室号)做到的,但是你不可能每次去你同学的寝室之前都问他的寝室号是多少,这样效率不高且没有礼貌(hhhh),在内存中同样如此,我们需要用一个变量来保存指针,即指针变量。

注:我们常说的指针其实是指针变量,指针实际上是一个地址(即寝室号)

在C语言中,我们使用 * 来表示指针变量

和定义其他类型变量有所不同的地方是, * 前面会再加一个类型,代表指针变量实际指向的地址所保存的内容是什么类型的

例如:

int a = 211;
int * p = &a;

在上图中 * 表示一个指针变量, 变量名为 p&a 表示取出 a 的地址,int 表示 a 实际保存的是一个int类型(* 表示寝室号, p 表示你把寝室号记在了一个叫 p 的日记本上,&a 表示你问同学他的寝室号是多少, * 前面的 int  表示 a 这个寝室号里面实际住的是你同学(是人这个类型),在这里我们是int类型)

你询问你的同学他的寝室号是多少这个行为是 &a, 你把他的寝室号记在一个名为 p 的日记本上, 当你下一次去找他寝室找他的时候 就可以直接看日记本(即直接访问 p 即可),而不需要再问他一次

1.3解地址操作符( * )

回到刚刚的例子,你的同学告诉了你他的寝室号为211,那么你很快就可以找到他寝室的位置,即是2楼第11个房间。

解地址操作符(*)相当于你找房间的这个过程

在内存中, * 后面加 变量/函数/数组 可以直接找到  该变量/函数/数组  

例如:

二.字符指针

2.1字符指针的定义

在1.2中我们介绍了 int 类型的指针(即整数类型指针),现在我们来了解一下字符指针

我们都知道定义一个字符在C语言中是通过如下方式

char c = 'w';

char 代表字符类型

字符类型指针就是字符指针,即 指针变量保存的地址中的内容类型是char

定义如下:

char c = 'w';
char * pc = &c;

2.2指针与字符串 

但假如每次只保存一个字符的地址,我想要输入一串字符串(例如:"Hello")难道要每个字符都保存在一个指针变量里面么?那样会显得太麻烦,因此我们规定字符类型指针也可以保存字符串的地址

定义如下:

char * pc = "Hello"; 

但这样又出现了一个新的问题,我们知道,当 保存一个字符  'w'  的地址的时候, pc 保存的就是 'w' 的地址,那当保存一个字符串 "Hello" 的地址的时候,是保存 首字母 H 的地址,还是把 Hello这五个字母的所有地址都保存在 pc 里面,还是随机保存 Hello 这五个字母中随机一个字母的地址?

我们可以测试一下,以下为测试答案:

由测试内容可知,pc 保存的不是整个字符串的地址,而是第一个字母的地址,所以当我们解地址时打印出来的是第一个字母 H。

那么怎么打印所有字母呢? 

 我们知道,一个字符所占内存为一个字节,我们假设第一个字符的地址为0xff1204(这里只是为了方便举例,实际地址要看编译器如何进行分配),字符串的所有地址如下:

而指针变量 pc+i (此时 i 等于0) 最先保存的地址为 0xff1204 指向 H 

 经过一次循环后 i 等于 1 ,pc+1保存的地址则为第二个字母的地址,*(pc+1)则找到第二个字母e,并打印出来

.....

.....

以此循环直到打印出所有字母 

三.数组指针

3.1数组指针的定义

同字符指针一样,数组指针指的是 指针保存的地址所指向内容是数组

我们定义一个数组变量是通过如下方式:

int arr[10] = {0};

其中 [ ] 表示定义的是一个数组变量,变量名为 arr ,int 表示 数组中保存的所有元素是 int 类型

数组指针可以进行类比得到如下定义方式:

int (* pArr) [10];

注意:  [ ] 的优先级高于 * ,如果不将 * 和 pArr 通过括号括起来,编译器将自动把 pArr 与后面的  [ ] 结合,那么int *  pArr[ ] 就是一个数组,数组中每个元素是int * 类型,而不是指针了

3.2数组指针的实例

int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int (* pArr)[10] = &arr;

如上述示例: * 与 pArr 先结合构成一个指针,[ ] 此时变成一个数组,int (* pArr)[10] 指 一个名为 pArr 的指针保存 一个数组的地址,该数组的元素有10个,元素的类型为 int

3.3如何使用数组指针

在介绍怎么使用数组指针之前,我们先看一个示例:

看上述代码的输出结果,我想要输出 数组 arr 的每一个元素,但输出的结果却完全不一样,这是为什么?

原因是在 *(pArr + i) 这里出现了问题

注意:arr 是数组名,同时也表示数组首元素的地址,但是存在两个例外

①sizeof 后面加数组名,此时数组名代表整个数组的地址

②& 后面加数组名,此时数组名代表整个数组的地址

在上述代码中,我们让

int (*pArr) [10] = &arr

 此时的 arr 代表的就是整个数组的地址

pArr指向整个数组

正确写法如下图所示:

 我们来解析一下 *(*(pArr)+i) 到底是怎么遍历数组中的每一个元素的

*(pArr) 保存的是数组的第一个元素的地址 

*(pArr) + i 保存的是数组中第i个元素的地址

*(*(pArr)+i)  是通过该数组第 i 个元素的地址找到第 i 个元素 

综上所述:可以理解为数组指针拥有两层外壳,当对 pArr 进行解地址操作时,只是去掉了第一层外壳,找到了整个数组的地址,如果要对 arr 数组中的单个元素进行操作的话,则需要进行第二次解地址操作,找到单个元素的地址 

以上仅是我个人对C语言指针的浅薄理解,如有错误,还请指正! 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值