seo建站是什么意思,和创客贴类似的网站,视频点播服务器,网站建设公司排名深圳今日伊雷娜#xff1a; 目录
前言#xff1a;
1、字符指针变量
1.1 使用字符指针存放字符
1.2 使用字符指针变量存放字符串 2、数组指针变量
2.1 什么是数组指针变量#xff1f;
2.2 数组指针变量初始化
2.3 关于数组指针类型的解析
3、函数指针变量
3.1 函数地址 …今日伊雷娜 目录
前言
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 使用字符指针存放字符
#include stdio.h
int main()
{char ch l;char* pc ch;//取出ch的地址放到ch里*pc l;return 0;
}
pc为字符指针变量指针变量是变量存放的是字符类型是char*
关于字符指针变量还有另外一种用法。也就是存放字符串。 1.2 使用字符指针变量存放字符串 char* p JonlyMay;//字符指针p指向了一个字符串 这句代码的意思是什么呢是把 JonlyMay字符串存放到指针变量p 中吗
重点p 中存放的是该字符串首字符的地址
我们来与数组类比理解 char* p JonlyMay中是将首元素地址赋给字符指针变量p char arr[ ] JonlyMay; char* p arr 我们创建了一个字符数组arr并把数组首元素地址arr赋给了pp变量里存放了数组首元素地址 我们可以用代码再来理解一下
#include stdio.h
int main()
{char arr[] JonlyMay;printf(%c\n, arr[2]);printf(%c\n, JonlyMay[2]);return 0;
}
可以把 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] ,我们怎么得到数组的地址呢 arrarr[0]表示首元素地址 arr表示的是数组的地址 数组的地址是 通过取地址数组名得到的arr 也就是说数组指针变量就是用来存放arr的 我们知道
字符指针变量的类型是字符指针(char*);
整型指针变量的类型是整型指针(int*),
那数组指针变量(parr)的类型是什么呢是数组指针吗好像是的但是应该怎么表达呢
我们举一个整型数组的例子
int main()
{int arr[10] { 0 };int* parr[10] arr;return 0;
}
乍一看似乎没毛病但是在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博客文章中关于arr1后跳过了40个字节
相信到这里应该能够理解为什么跳过40个字节了吧
arr的类型是数组指针int(*)[10]数组指针认为指向的数组有10个元素每一个元素类型都是int。所以1后跳过了4*10个字节。
总结数组指针变量是用来存放数组的地址数组的地址通过数组名获得将数组地址存起来放到数组指针变量中数组指针变量的类型就是 数组元素类型(*)[元素个数]
2.2 数组指针变量初始化
关于数组指针变量的初始化有两种方式
1、直接使用数组的地址进行初始化 例如对一个整型数组int arr[10]可以这样初始化
int (*p)[10] arr;
2、先声明数组指针变量然后在后续的代码中通过赋值来初始化。
int (*p)[5];p arr;
2.3 关于数组指针类型的解析
数组指针变量是一种特殊类型的指针它指向的是整个数组而不是单个元素。
数组指针变量的声明形式通常为 数据类型 (*指针变量名)[数组大小]
例如 int (*p)[5] 声明了一个指向包含 5 个整数的数组的指针 p 。
通过数组指针访问数组元素时通常需要结合下标来进行。
对于上述的 p(*p)[0] 表示数组的第一个元素(*p)[1]表示第二个元素以此类推。
图文总结
int (*p) [10] arr;| | || | || | p指向数组的元素个数| p是数组指针变量名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] 的形式可以访问数组中的第 i 个元素。
对于函数指针通过 (*pf)(int x, int y) 的形式可以调用所指向的函数并传递参数类型int ,int 注意 (int x, int y)中形参的x y是可以省略的只需要传递参数类型就可以了 pf就是函数指针变量 函数指针类型图解
int (*pf) (int x, int y) | | || | || | pf指向函数的参数类型和个数的交代| 函数指针变量名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; 我们怎么调用这个函数呢
#include stdio.h
int add(int x, int y)
{return x y;
}
int main()
{int (*pf)(int x, int y) add;int ret (*pf)(2, 3);//调用函数printf(%d,ret);return 0;
} 结果 int ret (*pf)(2, 3)解读 pf 是一个函数指针*pf 表示对函数指针进行解引用得到它所指向的函数。
然后 (*pf)(2, 3) 就是调用这个函数指针所指向的函数并向其传递参数 2 和 3。
最后将函数的返回值赋给变量 ret 。
3.5 补充函数调用
还记得我们正常函数调用是怎么操作的吗
#include stdio.h
int add(int x, int y)
{return x y;
}
int main()
{ int ret add(2, 3);printf(%d, ret);return 0;
} int (*pf)(int x, int y) add; int ret (*pf)(2, 3); 这个是指我们先将函数地址存放到指针变量pf中去然后我们通过函数指针变量来调用函数 我们来对比一下这两种调用方式
//第一种
int (*pf)(int x, int y) add;
int ret (*pf)(2, 3);
printf(%d, ret);
//第二种
ret add(2, 3);
printf(%d, ret);
前面我们说过add就是函数的地址pf中也是函数的地址那*pf为什么要解引用呢是否可以直接使用呢来测试一下 可以发现没有解引用pf也能直接使用所以在函数指针调用的时候 * 是可以省略的 它是没有实际意义的。
这里写*只是为了方便理解。
4、函数指针数组
数组是用来存放相同类型数据的存储空间在前面数组与指针这一篇中我们也介绍了指针数组的概念如
int * arr[10];//数组中的每个元素是int*
那要是把函数的地址存放到一个数组中那么这个数组就叫函数指针数组那函数指针的数组如何定义呢
int main()
{//指针数组int* arr[5]; //整型指针数组char* ch[5]; //字符指针数组return 0;
}
如果我们将函数指针也放在数组中呢
int add(int x, int y)
{return x y;
}
int sub(int x, int y)
{return x - y;
}
int main()
{int(*pa)(int, int) add;int(*ps)(int, int) sub;return 0;
}
从上面代码中我们可以发现pa,ps的类型是一样的既然如此我们就可以将他们放到一个数组中毕竟数组是用来存放相同类型数据的存储空间那我们如何创建一个函数指针数组呢 int ( * parr[4] )( int, int ) 这样写parr就变为数组名了有4个元素然后指针为parr[4];
如果我们把parr[4]去掉再看剩下的部分int ( * )( int, int ) 欸这不是一个函数指针类型也就是说我们创建的这个数组parr[4]的元素类型是函数指针所以我们所创建的这个数组就是函数指针数组。
这个函数指针数组是怎么创建的呢
我们只需要在函数指针变量的基础上在后面加上一个 [元素个数],就可以表示函数指针数组了
这时候这个数组就可以存放一些函数指针了
int (*parr[4])(int, int) { add,sub };
函数指针数组的作用数组的创建时为了方便更好的数据管理当我们想要存放多个函数的地址并且函数返回类型统一我们就可以造一个函数指针数组。 结语本篇文章到这里就结束了主要介绍了一些指针变量的用法希望大家在看完这篇文章后能够有所收获下篇再见啦