C:指针学习-指针变量—学习条记

[复制链接]
发表于 2026-2-8 04:42:21 | 显示全部楼层 |阅读模式
本日伊雷娜:

目次
媒介:
1、字符指针变量
1.1 利用字符指针存放字符
1.2 利用字符指针变量存放字符串
 2、数组指针变量
2.1 什么是数组指针变量?
2.2 数组指针变量初始化
2.3 关于数组指针范例的剖析
3、函数指针变量
3.1 函数所在
3.2 函数指针变量的创建
3.3 关于指针的连续界说
3.4 函数指针变量的利用
3.5 增补函数调用


媒介:

本篇文章涉及字符指针变量,数组指针变量,函数指针变量,以及函数指针数组。

1、字符指针变量

在指针范例中我们知道有一种指针范例叫char*
1.1 利用字符指针存放字符

  1. #include <stdio.h>
  2. int main()
  3. {
  4.         char ch = 'l';
  5.         char* pc = &ch;//取出ch的地址放到ch里
  6.         *pc = 'l';
  7.         return 0;
  8. }
复制代码
pc为字符指针变量,指针变量是变量,存放的是字符,范例是char*
关于字符指针变量尚有别的一种用法。也就是存放字符串。

1.2 利用字符指针变量存放字符串


       char* p = "JonlyMay";//字符指针p指向了一个字符串
  这句代码的意思是什么呢?是把  "JonlyMay"字符串存放到指针变量p 中吗?
重点:p 中存放的是该字符串首字符的所在
我们来与数组类比明确 char* p = "JonlyMay"中是将首元素所在赋给字符指针变量p:
   char arr[ ] = "JonlyMay";
char* p = arr
  我们创建了一个字符数组arr,并把数组首元素所在arr赋给了p,p变量里存放了数组首元素所在
  

  

  我们可以用代码再来明确一下
  1. #include <stdio.h>
  2. int main()
  3. {
  4.         char arr[] = "JonlyMay";
  5.         printf("%c\n", arr[2]);
  6.         printf("%c\n", "JonlyMay"[2]);
  7.         return 0;
  8. }
复制代码
可以把 "JonlyMay"想象成一个数组,[2]就访问下标为2的元素

    const char* p  = "JonlyMay"   //这里加上const的缘故起因是"JonlyMay" 是常量字符串,不能被修改的
  实在细致想想也不大概是将整个字符串都存放到指针变量p中,空间也不敷啊!
  p如果在x86的环境下,只能向内存申请4个字节的空间,而JonlyMay+\0有九个字节也放不下!
  总结:
const char* p  = "JonlyMay" 这串代码的意思是:把一个常量字符串首字符 J 的所在存放到指针变量 p 中。
 2、数组指针变量

2.1 什么是数组指针变量?

在先容数组指针变量之前,我们须要先提一下字符指针变量,整型指针变量,那这哥两是什么意思呢?
   (pc)字符指针变量是一种变量,内里存放的是(&ch)字符指针 (所在)
  char ch;
  char* pc = &ch;
  (pn)整型指针变量是一种变量,内里存放的是(&n)整型指针(所在)
  int n ;
  int* pn = &n;
  通过与它们的类比,我们应该能得出数组指针变量也是一种变量,内里存放的是数组指针(所在)
现在我们相识了指针数组指针变量的根本作用,那数组指针(所在) 怎么得到呢?
好比说 int arr[10] ,我们怎么得到数组的所在呢?
   arr,&arr[0]:体现首元素所在;
  &arr:体现的是数组的所在
  数组的所在是 通过取所在数组名得到的(&arr)
  也就是说数组指针变量就是用来存放&arr的
  我们知道
字符指针变量的范例是字符指针(char*);
整型指针变量的范例是整型指针(int*),
那数组指针变量(parr)的范例是什么呢?是数组指针吗?好像是的,但是应该怎么表达呢?
我们举一个整型数组的例子
  1. int main()
  2. {
  3.         int arr[10] = { 0 };
  4.         int* parr[10] = &arr;
  5.         return 0;
  6. }
复制代码
乍一看好像没毛病,但是在int* parr[10] = &arr中 int* 就变成了整型指针, parr和[10]团结变为数组了,parr是数组名,那int* parr[10] = &arr的意思就变成了一个名为parr的数组有10个元素,每个元素范例为int*。
但是我们想要的parr是一个指向数组的指针,应该怎么做呢?
实在这内里涉及到了利用符优先级的题目 ,如果对利用符优先级不太相识的,可以看一看博主关于利用符的博文:C:利用符先容-学习条记-CSDN博客
int* parr[10] = &arr,在这串代码中,parr先和[10]团结变成了数组,我们盼望得到的是一个指针变量parr,而当parr和[10]团结后就变为了数组名,得不到想要的效果。重要缘故起因是(*)利用符的优先级低于([ ])利用符
说了这么多,怎么办理呢?实在很简单,我们只须要利用圆括号()和 parr括起来就可以了

从上面的图中我们可以看到圆括号的优先级是最高的,以是当我们想得到一个指针,就须要* 和 parr先团结,而不是parr和[10]先团结
表达情势:int (*parr) [10] = &arr;
parr与*团结分析parr是指针,指针指向的是数组 [10]分析数组有10个元素,每个元素范例是int
现在这里的parr就是数组指针变量。
现在关于数组指针变量的表达情势我们已经很清楚了
那数组指针变量的范例是什么?int(*)[10]
int* pn = &n;中pn的范例就是int *
char* pc = &ch;中pc的范例就是char*;
以是变量的范例就是去掉变量名字,剩下的就是变量范例
int (*parr) [10] = &arr中parr的范例就是 int(*)[10],&arr的范例也是 int(*)[10]。
来举一个轻微有点难度的例子来资助我们更好的把握数组指针变量范例
颠三倒四:写到这突然想到一个很故意思的两句话,你已经学会加减乘除了,来,写道高数题练练手。
哈哈哈哈哈哈哈哈哈。(作者一样平常发癫,不必剖析)言归正传,来看一下标题
    int* arr[9] = { 0 };
 p = &arr;   
  问:这个p的范例是什么?
  答:int*(*)[9]
  起首,p先于*团结(*p),然后指向数组arr,有9个元素(*p)[9] ,数组中每个元素范例是int*,
  以是变为 int*(*p)[9] 。以是数组指针变量p的范例就是int*(*)[9]
  不知道各人是否还记得在这篇C:指针和数组之间的关系-学习条记-CSDN博客文章中关于&arr+1后跳过了40个字节
信赖到这里应该可以大概明确为什么跳过40个字节了吧!
&arr的范例是数组指针,int(*)[10],数组指针以为指向的数组有10个元素,每一个元素范例都是int。以是+1后跳过了4*10个字节。
总结:数组指针变量是用来存放数组的所在,数组的所在通过&数组名得到,将数组所在存起来放到数组指针变量中,数组指针变量的范例就是( 数组元素范例(*)[元素个数] )
2.2 数组指针变量初始化

关于数组指针变量的初始化有两种方式:
1、直接利用数组的所在举行初始化
比方对一个整型数组int arr[10],可以如许初始化;
  1. int (*p)[10] = &arr;
复制代码
2、先声明数组指针变量,然后在后续的代码中通过赋值来初始化。
  1. int (*p)[5];
  2.     p = &arr;
复制代码
2.3 关于数组指针范例的剖析

数组指针变量是一种特别范例的指针,它指向的是整个数组,而不是单个元素。
数组指针变量的声明情势通常为 数据范例 (*指针变量名)[数组巨细]
比方 int (*p)[5] 声明白一个指向包罗 5 个整数的数组的指针 p 。
通过数组指针访问数组元素时,通常须要团结下标来举行。
对于上述的 p,(*p)[0] 体现数组的第一个元素,(*p)[1]体现第二个元素,以此类推。
图文总结:
  1. int (*p) [10] = &arr;
  2. |    |    |
  3. |    |    |
  4. |    |    p指向数组的元素个数
  5. |    p是数组指针变量名
  6. p指向的数组的元素类型
复制代码
3、函数指针变量

3.1 函数所在

通过前面的学习我们知道变量可以取所在,数组也可以取所在。那么想问各人一个题目,函数有所在吗?函数可以取所在吗? 答案是函数有所在
既然函数有所在,我们该怎么得到呢?

上图中,我们可以发现想要得到函数的所在可以通过&函数名和函数名两种方式得到函数的所在
留意:
 对于函数来说,只有一个所在,这里不要和数组搞混了,数组中&数组名拿到的是数组首元素所在,但是函数不存在什么首元素所在。
3.2 函数指针变量的创建

既然我们知道函数的所在是怎么得到的时间,我们该怎么将函数所在存起来呢?
好比上面谁人add函数,我们想将它存到pf中,该怎么体现呢?pf的范例该怎么写呢?
   pf = &add;
  这里可以类比数组指针变量,int (*p) [10] = &arr;
照猫画虎,这里小编先把 pf 的范例写出来
   int (*pf)(int x, int y) = &add;
  类比int (*p) [10] = &arr;明确int (*pf)(int x, int y) = &add;
起首, int (*p) [10] = &arr; 中,p是一个数组指针,它指向的是一个包罗 10 个整数的数组。
而int (*pf)(int x, int y) = &add; 中,pf 是一个函数指针,它指向的是一个吸取两个int 范例参数并返回 int 范例值的函数。
就如同数组指针 p 通过 &arr 得到了指向数组的所在,函数指针 pf 通过 &add 得到了指向函数 add的所在。
对于数组指针,通过 (*p) 的情势可以访问数组中的第 i 个元素。
对于函数指针,通过 (*pf)(int x, int y) 的情势可以调用所指向的函数,并转达参数范例int ,int
   留意:
  (int x, int y)中形参的x y是可以省略的,只须要转达参数范例就可以了  
  pf就是函数指针变量
  函数指针范例图解:
  1. int    (*pf)    (int x, int y)
  2. |       |            |
  3. |       |            |
  4. |       |            pf指向函数的参数类型和个数的交代
  5. |       函数指针变量名
  6. pf指向函数的返回类型
复制代码
3.3 关于指针的连续界说

   如果是连续界说两个整数,我们可以这么写
  int a , b;
  那如果是来连续界说两个指针呢?我们还可以这么写吗?
  int* a , b;
  答案是不对的;我们可以来看一下
  

  当我们将鼠标放到a上时,可以看到a的范例是 int*
  但是当我们将鼠标放到b上时,可以看到b的范例是 int
  以是,关于来纳许界说两个指针我们须要每一个变量都有*
  正确表达情势:int *a , *b;
  3.4 函数指针变量的利用

我们将函数所在存放起来,是为了背面的利用,那么我们应该怎么利用呢?
   int (*pf)(int x, int y) = &add;
  我们怎么调用这个函数呢?
  1. #include <stdio.h>
  2. int add(int x, int y)
  3. {
  4.         return x + y;
  5. }
  6. int main()
  7. {
  8.         int (*pf)(int x, int y) = &add;
  9.         int ret = (*pf)(2, 3);//调用函数
  10.     printf("%d",ret);
  11.         return 0;
  12. }
复制代码
 效果:

 int ret = (*pf)(2, 3)解读:
 pf 是一个函数指针,*pf 体现对函数指针举行解引用,得到它所指向的函数。
然后 (*pf)(2, 3) 就是调用这个函数指针所指向的函数,并向其转达参数 2 和 3。
末了,将函数的返回值赋给变量 ret  。
3.5 增补函数调用

还记得我们正常函数调用是怎么利用的吗?
  1. #include <stdio.h>
  2. int add(int x, int y)
  3. {
  4.         return x + y;
  5. }
  6. int main()
  7. {       
  8.         int ret = add(2, 3);
  9.         printf("%d", ret);
  10.         return 0;
  11. }
复制代码
  int (*pf)(int x, int y) = &add;
  int ret = (*pf)(2, 3);
  这个是指我们先将函数所在存放到指针变量pf中去,然后我们通过函数指针变量来调用函数
  我们来对比一下这两种调用方式
  1. //第一种:
  2. int (*pf)(int x, int y) = &add;
  3. int ret = (*pf)(2, 3);
  4. printf("%d", ret);
  5. //第二种:
  6. ret = add(2, 3);
  7. printf("%d", ret);
复制代码
前面我们说过add就是函数的所在,pf中也是函数的所在,那*pf为什么要解引用呢?是否可以直接利用呢?来测试一下

可以发现没有解引用pf也能直接利用,以是在函数指针调用的时间 是可以省略的 ,它是没有现实意义的。
这里写*只是为了方便明确。
4、函数指针数组

数组是用来存放类似范例数据的存储空间,在前面数组与指针这一篇中我们也先容了指针数组的概念,如:
  1. int * arr[10];//数组中的每个元素是int*
复制代码
那要是把函数的所在存放到一个数组中,那么这个数组就叫函数指针数组,那函数指针的数组怎样界说呢?
  1. int main()
  2. {
  3.         //指针数组
  4.         int* arr[5]; //整型指针数组
  5.         char* ch[5]; //字符指针数组
  6.         return 0;
  7. }
复制代码
如果我们将函数指针也放在数组中呢?
  1. int add(int x, int y)
  2. {
  3.         return x + y;
  4. }
  5. int sub(int x, int y)
  6. {
  7.         return x - y;
  8. }
  9. int main()
  10. {
  11.         int(*pa)(int, int) = add;
  12.         int(*ps)(int, int) = sub;
  13.         return 0;
  14. }
复制代码
从上面代码中我们可以发现pa,ps的范例是一样的,既然云云,我们就可以将他们放到一个数组中,究竟数组是用来存放类似范例数据的存储空间,那我们怎样创建一个函数指针数组呢?
   int ( * parr[4] )( int, int )
  如许写parr就变为数组名了,有4个元素,然后指针为parr[4];
如果我们把parr[4]去掉再看剩下的部分int ( *  )( int, int ) ,欸,这不是一个函数指针范例,也就是说我们创建的这个数组parr[4]的元素范例是函数指针,以是我们所创建的这个数组就是函数指针数组。
这个函数指针数组是怎么创建的呢?
我们只须要在函数指针变量的底子上,在背面加上一个 [元素个数],就可以体现函数指针数组了
这时间这个数组就可以存放一些函数指针了
  1. int (*parr[4])(int, int) = { add,sub };
复制代码
函数指针数组的作用:数组的创建时为了方便更好的数据管理,当我们想要存放多个函数的所在,而且函数返回范例同一,我们就可以造一个函数指针数组。

结语:本篇文章到这里就竣事了,重要先容了一些指针变量的用法,盼望各人在看完这篇文章后可以大概有所劳绩!下篇再见啦!!!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表