当前位置:网站首页>二级指针,数组指针,指针数组和函数指针
二级指针,数组指针,指针数组和函数指针
2022-08-02 14:02:00 【iccoke】
二级指针
二级指针就是指向一级指针的指针,二级指针里面存放的是一级指针的地址
一般前情况下定义为
int *p=&a;
int **q=&p;
二级指针指向一级指针,一级指针指向变量a
那么关于二级指针的使用也和一级指针相同,在不加限定条件下的情况下可以通过二级指针进行两次解引用访问一级指针指向的变量的值;
**q=10;
但是普遍的情况是会对 二级指针在定义上出现限定
例如 const与二级指针的结合,上一节我们对const和一级指针的结合有了了解,现在我们来了解const和二级指针的结合
例如在这里,我们对每一行代码进行分析,用const修饰后的部分可以看作常量,也就以为着不能对它进行操作。
const int *p;用const修饰了*p,也就意味着我们不能通过解引用来修改p指向的变量的值,但是可以改变它的指向,所以*p=10;错误 p=&b;正确
int *const q;用从const修饰了p,也就是说可以用*p来修改指向变量的值,但是不可以改变它的指向
const int **s;同理,不能进行二级解引用,但是可以改变它的指向
int*const*t;不能改变指向,但是可以解引用
const int *const*z;这里是const修饰了**z和*z,这意味着即不可以解引用也不能改变指向
这是一般的情况,那么如果再特殊一点,a和b都用const修饰,那么该做出怎么样的修改
a,b都用const修饰,那么不管是间接或者直接修改a,b的值的语句都是错误的,在定义指针时也要注意,如果用普通的一级指针或者二级指针定义,那么必然就可以通过解引用来对a,b值进行修改,但是前提是a,b的值不能进行修改,因此出现矛盾,所以在这种情况下,定义时一定要用const修饰*q和**t,那么*t需不需要进行const修饰则根据场景进行修改即可。
数值指针
定义 int (*p)[n];
()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。
如要将二维数组赋给一指针,应这样赋值:
int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
p=a; //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
p++; //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]
所以数组指针也称指向一维数组的指针,亦称行指针
这里可以看到arr和&arr[0]都是一样的,括号表示这里侧重的是指针,都表示的是第一行首元素的地址,如果对p进行加一操作,那么指针就会指向到第二行首元素的地址,所以p+1后,增加了四个int
那么要一个一个的访问二维数组的元素,就要定义为int*s=&arr[0][0],这样s+1就会一个一个的访问二维数组的每一个元素
int (*p)[4] = arr;
//p++; p + 4个int
int(*q)[4] = &arr[0];
//q++; q + 4个int
int* s = &arr[0][0];
//s++; //s + 1个 int
int (*w)[3][4]= &arr;
//w++; //w + 12个int
指针数组
一维指针数组的定义形式为:"类型名 *数组标识符[数组长度]"。
例如,一个一维指针数组的定义:int *ptr_array[10]。
比如 const char*arr[5]={"hello","world"}
然后访问这个数组 char*p=arr[0],那么这里arr[0]就代表了数组首元素的地址,即”hello“
那么我们想访问hello中的h又该如何访问呢,这里我们可以用
const char* str[2] = {"hello","world"};
const char** p = &str[0];
printf("%s\n", *(p + 1))
这里就可以访问到
函数指针
int add(int a, int b) {
return a + b;
}
int mul(int a, int b) {
return a * b;
}
int main(){
int a, b;
char op[10] = {0}; //"+" "*"
scanf("%d%d",&a,&b);
scanf("%s", &op);
//定义一个函数指针,指向add 指向mul
int (*pfun)(int, int);
//声明一个指针变量
// 函数指针类型
if (strcmp(op,"+") == 0) {
pfun = add;
}
else {
pfun = mul;
}
int result = pfun(a, b);
printf("%d\n",result);
}
这里就可以看到函数的参数类型相同,返回值类型相同,就可以用一个函数指针指向函数,这就是函数指针
typedef
这个的作业的是函数重命名
例如
int *p,q;
那么这个时候的p,和q分别是什么类型的变量呢,其实p是指针变量,q是int类型的变量
那么我们可以使用宏
#define point_32 int*
但是这个宏只在预编译环节起作用,其实还是没有作用
这个时候我们就可以使用typedef
typedef int* point_32意思是将int*重命名为point_32
那么在下面就可以使用
point_32 p,q
那么p,q就都是指针变量
scanf函数的缓冲区
在刚刚的函数指针中
int a, b;
char op[10] = {0}; //"+" "*"
scanf("%d%d",&a,&b);
scanf("%c", &op);
如果在这里将a,b,op输出出来,就会发现输出a,b后程序就会结束
这是因为输出a,b回车后,系统无法识别这个回车是op还是换行动作,就会出现这个情况
解决方法是输入完整形之后,再进行一个字符\n的获取,获取后不用(目的是将其从缓冲区中剔除,继而获得下一个有效数据)
可以这样解决
scanf("%d",&a);
scanf("%c",&num);//一般使用getchar()
scanf("%d",&c);
或者使用其他函数
putchar()
getchar()
gets()
puts()
在输入输出字符串的时候我们就可以使用这些函数。
边栏推荐
- [ROS](02)创建&编译ROS软件包Package
- C语言sizeof和strlen的区别
- verilog学习|《Verilog数字系统设计教程》夏宇闻 第三版思考题答案(第十二章)
- The IDEA of packaged jar package
- drf routing component Routers
- Flask framework in-depth two
- 猜数字游戏,猜错10次关机(srand、rand、time)随机数生成三板斧(详细讲解!不懂问我!)
- [ROS] The difference between roscd and cd
- 8581 Linear linked list inversion
- ToF相机从Camera2 API中获取DEPTH16格式深度图
猜你喜欢
随机推荐
yolov5,yolov4,yolov3 mess
Hands-on OCR (1)
Raft协议图解,缺陷以及优化
第十一单元 序列化器
Flask框架深入一
php开源的客服系统_在线客服源码php
Flask contexts, blueprints and Flask-RESTful
【Camera2】由Camera2 特性想到的有关MED(多场景设备互动)的场景Idea
跑跑yolov5吧
Briefly write about the use and experience of PPOCRLabel
Linux: CentOS 7 install MySQL5.7
redis分布式锁和看门狗的实现
海明校验码纠错设计原理
Flask上下文,蓝图和Flask-RESTful
Sentinel源码(五)FlowSlot以及限流控制器源码分析
网络剪枝(1)
Go语言初始
Creating seven NiuYun Flask project complete and let cloud
[ROS] (05) ROS Communication - Node, Nodes & Master
xshell连接虚拟机步骤_建立主机与vm虚拟机的网络连接