「1」指针进阶——详解

简介: 🐰指针的回顾🐰字符指针🐰指针数组🌸模拟二维数组(整形)🐰数组指针🌸数组指针和指针数组的区分🌸&数组名和数组名的区别🌸数组指针p,*p等价于arr,*p就是数组名🌸数组指针的使用🌸数组参数和指针参数🐰函数指针-指向函数的指针🌸函数指针数组

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

🐰指针的回顾

🐰字符指针

🐰指针数组

🌸模拟二维数组(整形)

🐰数组指针

🌸数组指针和指针数组的区分

🌸&数组名和数组名的区别

🌸数组指针p,*p等价于arr,*p就是数组名

🌸数组指针的使用

🌸数组参数和指针参数

🐰函数指针-指向函数的指针

🌸函数指针数组


🐰指针的回顾

1.指针是内存中一个最小单元的编号,也就是地址

2.平时口语上所说的指针,通常指的是指针变量,是用来存放地址的变量

3.把内存划分为一个个的内存单元,这个内存单元大小是1字节,从概念上讲:编号 == 地址 == 指针

指针变量:

我们可以通过& (取地址操作符) 取出变量的内存起始地址,把地址可以存放到一个变量中,这个变量就是指针变量

4.指针大小(4字节 32位/8字节 64位)

🐰字符指针

1. #include<stdio.h>
2. int main()
3. {
4.     char ch='w';
5.     char* pc=&ch;
6.     const char* p="abcdef";//"abcdef",是把字符串的首地址放到p中
7.     //"abcdef"是常量字符串,是不可以修改的
8.     char arr[]="abcdef";
9.     //"abcdef",这里的arr的值是可以修改的
10.     char *pa=arr;
11.     *pa='w';
12.     printf("%s\n",arr);//修改的结果为wbcdef
13.     return 0;
14. }

‼️注:常量字符串在内存中只保存一份!!!

1. #include<stdio.h>
2. int main()
3. {
4.     char str1[]="abcdef";
5.     char str2[]="abcdef";
6. 
7.     char* str3="abcdef";//保存的就是常量字符串
8.     char* str4="abcdef";//保存的就是常量字符串
9.     if(str1==str2)//数组保存的字符串是变量,所以str1!=str2
10.     {
11.         printf("str1==str2\n");
12.     }
13.     else
14.     {
15.         printf("str1!=str2\n");
16.     }
17.     if(str3==str4)//常量字符串在内存中只保留一份,所以str3==str4
18.     {
19.         printf("str3==str4\n");
20.     }
21.     else
22.     {
23.         printf("str3!=str4\n");
24.     }
25.     return 0;
26. }

结果为:

str1!=str2

str3==str4

🐰指针数组

字符数组-存放字符的数组

char arr[10];

整形数组-存放整形的数组

int arr[10];

指针数组-存放的就是指针

char* arr[10];

int* arr[10];

1. #include<stdio.h>
2. int main()
3. {
4.     char* arr[]={"abc","bcd","edf"};//指针数组,保存了三个字符串的首地址
5.     for(int i=0;i<3;i++)
6.     {
7.         printf("%s\n",arr[i]);
8.     }
9.     return 0;
10. }

结果为:

abc

bcd

edf

🌸模拟二维数组(整形)

1. #include<stdio.h>
2. int main()
3. {
4.     int arr1[]={1,2,3,4,5};
5.     int arr2[]={1,2,3,4,5};
6.     int arr3[]={1,2,3,4,5};
7.     int arr4[]={1,2,3,4,5};
8.     int* arr5[]={arr1,arr2,arr3,arr4};
9.     for(int i=0;i<4;i++)
10.     {
11.         for(int j=0;j<5;j++)
12.         {
13.             printf("%d",*(arr5[i]+j));
14.             //printf("%d\n",arr5[i][j]);//结果一样
15.         }
16.         printf("\n");
17.     }
18.     return 0;
19. }

结果为:

12345

12345

12345

12345

🐰数组指针

整形指针-指向整形的指针

int a=10;

int* P=&a

字符指针-指向字符的指针

char ch='w';

char* pc=&ch;

数组指针-指向数组的指针

int arr[10];

&arr就是数组的地址

int (*pa)[10]=&arr;

char arr[10];

char(*pc)[10]=&arr

int* arr[5];

int* (*pa)[5]=&arr//这个数组指针指向的是arr这个指针数组

🌸数组指针和指针数组的区分

指针数组->存放指针的数组

数组指针->是一种指向数组的指针-存放的是数组的地址

🌸&数组名和数组名的区别

数组名是数组首元素地址

sizeof(数组名)--这个时候表示的不是首元素的首地址,计算的整个数组的大小

&数组名--这里的数组名表示整个数组,取出的是整个数组的地址,从地址角度看和数组首元素的地址一样,他们的类型不一样

1. #include<stdio.h>
2. int main()
3. {
4.     int arr[10]={0};
5.     printf("arr=%p\n",arr);//数组首元素的地址
6.     printf("arr+1=%p\n",arr+1);//数组第二个元素的地址
7. 
8.     printf("&arr[0]=%p\n",&arr[0]);//数组首元素的地址
9.     printf("&arr[0]+1=%p\n",&arr[0]+1);//数组第二个元素的地址
10. 
11.     printf("&arr=%p\n",&arr);//整个数组的地址
12.     printf("&arr+1=%p\n",&arr+1);//数组第最后一个元素的下一个的地址
13.     int(*p)[10]=&arr;//数组指针保存整个数组的地址
14.     return 0;
15. }

结果

r=0x7ffeefbff3c0

arr+1=0x7ffeefbff3c4

&arr[0]=0x7ffeefbff3c0

&arr[0]+1=0x7ffeefbff3c4

&arr=0x7ffeefbff3c0

&arr+1=0x7ffeefbff3e8

🌸数组指针p,*p等价于arr,*p就是数组名

1. #include<stdio.h>
2. int main()
3. {
4.     int arr[10]={1,2,3,4,5,6,7,8,9,10};
5.     int (*p)[10]=&arr;
6.     for(int i=0;i<10;i++)
7.     {
8.         printf("%d ",*((*p)+i));//*p等价于arr,*p就是数组名
9.     }
10.     return 0;
11. }

结果为:

1 2 3 4 5 6 7 8 9 10

🌸数组指针的使用

1. #include<stdio.h>
2. void print(int (*arr)[5],int r,int c)
3. {
4.     for(int i=0;i<r;i++)
5.         {
6.             for(int j=0;j<c;j++)
7.             {
8.                 printf("%d ",*(*(arr+i)+j));//arr+i==&arr[i]
9.                 //printf("%d ",arr[i][j]);
10.             }
11.         }
12. }
13. int main()
14. {
15.     //二维数组的数组名,也表示首元素地址
16.     //二维数组的首元素是第一行的地址,是一个一维数组的地址
17.     int arr[3][5]={1,2,3,4,5,6,7,8,9,10};
18.     print(arr,3,5);
19.     return 0;
20. }

结果为:

1 2 3 4 5 6 7 8 9 10 0 0 0 0 0

二维数组arr

int (*p)[10]=&arr;

p等价于arr

arr=&arr[i]

arr[i]=&arr[i][0]

分析代码

int arr[5];

int *parr1[10];//指针数组

int (*parr2)[10];//数组指针

int (*parr3[10])[5];//数组中存放的数组指针

🌸数组参数和指针参数

一维数组传参

一维数组传参,形参可以是数组,可以是指针

二维数组传参

参数可以是指针,可以是数组,如果是指针,传过去的是第一行的地址

函数形参的设计只能省略第一个[]的数字,因为一个二维数组,可以不知道有对少行,但是必须知道一行有多少元素

一级指针传参

当一个函数的参数部分为一级指针的时候,函数能接收什么参数

数组,指针

二级指针传参

当一个函数的参数部分为二级指针的时候,函数能接收什么参数

二级指针变量,一级指针的地址,指针数组

🐰函数指针-指向函数的指针

函数指针存放的是函数的地址,函数也是有地址的

‼️注:函数名和取地址函数名 是一样的

1. #include<stdio.h>
2. int Add(int x,int y)
3. {
4.     return x+y;
5. }
6. //函数是存在地址
7. int main()
8. {
9.     printf("%p\n",&Add);//0x100003f40
10.     printf("%p\n",Add);//0x100003f40
11.     int (*pf)(int,int)=Add;//pf就是函数指针
12. 
13.     int ret=(*pf)(3,5);//函数指针的调用
14.     int rat=pf(3,5);//*pf和pf等价
15.     //这里的*没有实际的意义,可以不要pf(3,5),可以多加(**pf)(3,5),都不影响结果,*pf)(3,5)是为了方便理解
16.     printf("%d %d\n",ret,rat);
17. }

结果为:

0x100003ef0

0x100003ef0

8 8

🌸函数指针数组

数组的每个元素是一个函数指针

这是利用switch()语句制作的两位数计算器

1. #include<stdio.h>
2. int Add(int x,int y)
3. {
4.     return x+y;
5. }
6. int Sub(int x,int y)
7. {
8.     return x-y;
9. }
10. int Mul(int x,int y)
11. {
12.     return x*y;
13. }
14. int Div(int x,int y)
15. {
16.     return x/y;
17. }
18. void menu(void)
19. {
20.     printf("****    两位数的计算器     ****\n");
21.     printf("****    1.Add   2.Sub   ****\n");
22.     printf("****    3.Mul   4.Div   ****\n");
23.     printf("****    0.exit          ****\n");
24. }
25. int main()
26. {
27. 
28.     int input=0;
29.     do
30.     {
31.         menu();
32.         printf("请选择\n");
33.         scanf("%d",&input);
34.         int x=0,y=0,ret=0;
35.         switch(input)
36.         {
37.             case 1:
38.                 printf("请输入两个操作数\n");
39.                 scanf("%d %d",&x,&y);
40.                 ret=Add(x,y);
41.                 printf("%d\n",ret);
42.                 break;
43.             case 2:
44.                 printf("请输入两个操作数\n");
45.                 scanf("%d %d",&x,&y);
46.                 ret=Sub(x,y);
47.                 printf("%d\n",ret);
48.                 break;
49.             case 3:
50.                 printf("请输入两个操作数\n");
51.                 scanf("%d %d",&x,&y);
52.                 ret=Mul(x,y);
53.                 printf("%d\n",ret);
54.                 break;
55.             case 4:
56.                 printf("请输入两个操作数\n");
57.                 scanf("%d %d",&x,&y);
58.                 ret=Div(x,y);
59.                 printf("%d\n",ret);
60.                 break;
61.             default:
62.                 printf("输入错误\n");
63.         }
64.     }while(input);
65. }

结果为:

****      两位数的计算器     ****

****      1.Add   2.Sub        ****

****      3.Mul   4.Div         ****

****      0.exit                      ****

请选择

1

请输入两个操作数

3 8

11

这种算法,太冗余了,不够简洁

这是利用函数指针数组制作的两位数计算器

1. #include<stdio.h>
2. int Add(int x,int y)
3. {
4.     return x+y;
5. }
6. int Sub(int x,int y)
7. {
8.     return x-y;
9. }
10. int Mul(int x,int y)
11. {
12.     return x*y;
13. }
14. int Div(int x,int y)
15. {
16.     return x/y;
17. }
18. void menu(void)
19. {
20.     printf("****    两位数的计算器     ****\n");
21.     printf("****    1.Add   2.Sub   ****\n");
22.     printf("****    3.Mul   4.Div   ****\n");
23.     printf("****    0.exit          ****\n");
24. }
25. int main()
26. {
27.     int input=0;
28.     do
29.     {
30.         int x=0,y=0;
31.         menu();
32.         printf("请选择\n");
33.         scanf("%d",&input);
34.         printf("请输入两个操作数\n");
35.         scanf("%d %d",&x,&y);
36.         int (*pf[5])(int,int)={0,Add,Sub,Mul,Div};//这里之所以数组元素给了5个,是为了与菜单对应起来
37.         if(input<5&&input>=0)
38.         {
39.             int ret=(*pf[input])(x,y);
40.             printf("%d\n",ret);
41.         }
42.         else if(input==0)
43.         {
44.             printf("计算结束\n");
45.             break;
46.         }
47.         else
48.         {
49.             printf("输入错误\n");
50.         }
51.     }while(input);
52. }

结果为:

****      两位数的计算器     ****

****      1.Add   2.Sub        ****

****      3.Mul   4.Div         ****

****      0.exit                      ****

请选择

1

请输入两个操作数

3 8

11

这种算法,很简洁,逻辑更清晰。

🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸      

相关文章
|
3月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
3月前
|
机器学习/深度学习 搜索推荐 算法
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
|
3月前
|
C语言
指针进阶(回调函数)(C语言)
指针进阶(回调函数)(C语言)
|
3月前
|
存储 C语言 C++
指针进阶(函数指针)(C语言)
指针进阶(函数指针)(C语言)
|
3月前
|
编译器 C语言
指针进阶(数组指针 )(C语言)
指针进阶(数组指针 )(C语言)
|
3月前
|
搜索推荐
指针进阶(2)
指针进阶(2)
39 4
|
3月前
指针进阶(3)
指针进阶(3)
32 1
|
3月前
|
C++
指针进阶(1)
指针进阶(1)
35 1
|
3月前
|
存储 安全 编译器
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
33 2
|
3月前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
36 0