🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
目录
🐰指针的回顾
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
这种算法,很简洁,逻辑更清晰。
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸