重新回顾指针:
C语言指针笔记01 - Morning枫 - 博客园 (cnblogs.com)
&ptr 输出指针变量ptr的地址
ptr 输出指针变量ptr保存的地址(一个十六进制的地址,若输出采用%d,则输出一个整数)//字符串自身的地址就是它本身的值
*ptr 输出指针变量ptr保存的地址的值(相当于直接找到地址修改地址保存的值)
由于指针也是个变量,所以它自己本身也可以进行算术运算:
地址+1,但是定义是int的指针,int有四字节,所以指针保存的地址在内存中+4,即指向数组中下一个元素
实机演示运行一次:
自增如此,同理可推自减。
指针加/减运算:
已经理解自增和自减,加减也不在话下!
此代码表示,指针指向数组当前位置的后面第二位元素
指针的比较:
直接上案例进行判断:
1.
输出为:ok2和ok3
分析过程:
============================================
2.
输出为:
Address of var[0] = 指向10的地址
Value of var[0] = 10
Address of var[00] = 指向100的地址
Value of var[1] = 100
此案例进行的是地址的比较。。。
指针数组:
实例:
当执行完:
int i, *ptr[3];
内存中有:
执行完第一个循环体后,有如下内存图变化:
此时被称为指针数组
接着,用指针数组来获取各个值:
完整代码如下:
1 #include <stdio.h> 2 3 const int MAX = 3; 4 5 int main(){ 6 int var[] = {10,100,200}; 7 int *ptr[3]; 8 for(int i = 0; i < MAX; i++){ 9 ptr[i] = &var[i]; 10 } 11 for(int i = 0; i < MAX; i++){ 12 printf("Value of var[%d] = %d\n", i, *ptr[i]); 13 } 14 return 0; 15 }
实例运用:
1 #include <stdio.h> 2 3 const int MAX = 4; 4 5 int main(){ 6 char *books[] = {"西游记","水浒传","红楼梦","三国演义"}; 7 8 for(int i = 0; i < MAX; i++){ 9 printf("Value of var[%d] = %s\n", i, books[i]); //字符串本身就是地址,不用*books[] 10 } 11 }
&ptr 输出指针变量ptr的地址
ptr 输出指针变量ptr保存的地址(一个十六进制的地址,若输出采用%d,则输出一个整数)//字符串自身的地址就是它本身的值
*ptr 输出指针变量ptr保存的地址的值(相当于直接找到地址修改地址保存的值)
多重指针数组(指向指针的指针):
快速入门:
1 #include <stdio.h> 2 3 int main(){ 4 int var; 5 int *ptr; 6 int **pptr; 7 var = 3000; 8 ptr = &var; //把var变量的地址赋值给ptr 9 pptr = &ptr; //把ptr存放的地址赋值给pptr 10 printf("var的地址=%p var=%d\n", &var, var); 11 printf("ptr本身的地址=%p ptr存放的地址=%p ptr=%d\n", &ptr, ptr, *ptr); 12 printf("pptr本身的地址=%p pptr存放的地址=%p pptr=%d\n", &pptr, pptr, **pptr); 13 return 0; 14 }
内存图示例:
更多级的指针可以从二级指针理解和去推导即可。
传递指针给函数:
案例1(传递指针/地址给指针变量)入手:
1 #include <stdio.h> 2 3 //函数写在main前就不用声明,写在main后就需要在前面声明 4 void test2(int *p); //函数声明,接收int * 5 6 void main(){ 7 int num = 90; 8 int *p = # //把num地址赋值给p 9 test2(&num); //传地址 10 printf("\n main()中的num=%d", num); 11 test2(p); //传指针 12 printf("\n main()中的num=%d", num); 13 } 14 15 void test2(int *p){ 16 *p += 1; 17 }
内存示意图:
案例2(传数组给指针变量)入手:
首先确认:
指针数组传递的是地址,而不是值,因此操作过程中有且只有一个数组(理解为全局)在被操作,而不是和值一样操作值的副本(理解为局部)
1 #include <stdio.h> 2 3 //函数声明 4 double getAverage(int *arr, int size); 5 double getAverage2(int *arr, int size); 6 7 int main(){ 8 int balance[5] = {1000,2,3,17,50}; //定义带有五个元素的int数组 9 double avg; 10 avg = getAverage(balance, 5); //传递以一个指向数组的指针作为参数 11 printf("Average value is: %f\n", avg); 12 return 0; 13 } 14 15 double getAverage(int *arr, int size){ //下标遍历 16 int i, sum = 0; 17 double avg; 18 for( i = 0; i < size; i++){ 19 sum += arr[i]; //数组下标运算 20 printf("\n arr存放的地址=%p", arr); //不改变arr的地址,只对下标进行修改 21 } 22 avg = (double)sum / size; 23 return avg; 24 } 25 26 double getAverage2(int *arr, int size){ //指针遍历 27 int i, sum = 0; 28 double avg; 29 for( i = 0; i < size; i++){ 30 sum += *arr; //地址运算 31 printf("\n arr存放的地址=%p", arr); 32 arr++; //指针的自增运算,会对arr存放的地址做修改 33 //arr[0] = arr + 0 34 //arr[1] = arr + 1个int的字节(4) 35 //arr[2] = arr + 2个int的字节(8) 36 } 37 avg = (double)sum / size; 38 return avg; 39 }
内存图:
返回指针的函数:
快速入门:
1 #include <stdio.h> 2 #include <string.h> 3 4 char *strlong(char *str1, char *str2){ //表明此函数是一个指针函数 5 printf("\n str1的长度是:%d,str2的长度是:%d", strlen(str1), strlen(str2)); 6 if(strlen(str1) >= strlen(str2)){ 7 return str1; 8 }else{ 9 return str2; 10 } 11 } 12 13 int main(){ 14 char str1[30], str2[30], *str; //str是一个指针类型,指向一个字符串 15 printf("\n请输入第一个字符串:"); 16 gets(str1); 17 printf("\n请输入第二个字符串:"); 18 gets(str2); 19 str = strlong(str1, str2); 20 printf("\n Longer string:%s \n", str); 21 return 0; 22 }
返回函数指针的有关注意事项:
关于第一点和第二点,需要深刻理解!!!:
1 #include <stdio.h> 2 3 int *func(){ 4 int n = 100; //局部变量 5 return &n; 6 } 7 8 int main(){ 9 int *p = func(); //func返回指针 10 int n; 11 n = *p; 12 printf("\n value = %d \n", n); //所以最后不一定能输出100 13 return 0; 14 }
对于函数返回销毁,它只是放弃了需要返回的函数的使用权限,但是其中内存改变的值并没有重新初始化(只要没有代码调用新的内存(例如printf会调用内存,此时可能会重新给之前返回的函数占用的内存重新赋值,从而导致返回的值被覆盖)),只要在执行其他代码前调用了返回函数的值,就有可能正常运行输出返回的值。具体看第三点。。
关于第三点,进行了static修饰后,即可正常运行上面的案例程序:
1 #include <stdio.h> 2 3 int *func(){ 4 static int n = 100; //如果这个局部变量是static性质的,那么它将保存在内存中的静态数据区 5 return &n; 6 } 7 8 int main(){ 9 int *p = func(); //func返回指针 10 int n; 11 n = *p; 12 printf("\n value = %d \n", n); //所以最后不一定能输出100 13 return 0; 14 }
关于static的用法:
static 关键字 - Morning枫 - 博客园 (cnblogs.com)
应用实例:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int *random1(){ 5 static int arr[10]; //让arr的空间在静态数据区保存 6 for(int i = 0; i < 10; i++){ 7 arr[i] = rand(); 8 } 9 return arr; 10 } 11 12 void main(){ 13 int *p; 14 p = random1(); //p指向在random1生成的数组的首地址(即第一个元素的地址) 15 for(int i = 0; i < 10; i++){ 16 printf("\n%d",*(p+i)); 17 } 18 }
函数指针:
定义:
实例演示:
1 #include <stdio.h> 2 3 int max(int a, int b); 4 5 int main(){ 6 int x, y, maxVal; 7 //函数指针 8 //函数指针名字是pmax 9 //int表示该函数指针指向的函数是返回int类型 10 //(int , int)表示该函数指针指向的函数形参是接收两个int 11 //要注意这个函数指针是有地址的 12 //在定义函数指针时,也可以写形参名(可以不与指向的函数形参名或者传递的变量名相同),如:int (*pmax)(int i, int j) = max; 13 //简单理解为:本身有地址的pmax函数指针保存了max函数的地址// 14 int (*pmax)(int, int) = max; 15 printf("Input two numbers:"); 16 scanf("%d%d", &x, &y); 17 maxVal = (*pmax)(x,y); //通过函数指针去调用参数,即*pmax-->max,当然也可以写成pmax(x,y)也是允许的 18 //类似于*pmax取到了函数max的首地址 19 //maxVal = max(x,y); 20 printf("Max value = %d\n", maxVal); 21 printf("pmax保存的地址:%p,pmax本身的地址:%p", pmax, &pmax); 22 return 0; 23 } 24 25 int max(int a,int b){ //Max函数,接收两个int,返回值大的 26 return a>b ? a:b; 27 }
内存图:
函数指针——回调函数:
介绍:
实例:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 //回调函数 5 //int (*f)(void),f是一个函数指针,它可以接收的函数是返回int,没有形参的参数 6 //f在这被initArray调用,充当了回调函数的角色 7 void initArray(int *array, int arraySize, int (*f)(void)){ 8 int i; 9 for(i = 0; i < arraySize; i++){ 10 array[i] = f(); //通过函数指针调用getNextRandomValue函数,(*f)()=f() 11 } 12 } 13 14 //获取随机值 15 int getNextRandomValue(void){ 16 return rand(); //rand系统函数,会返回一个随机整数 17 } 18 19 int main(){ 20 int myarray[10], i; //定义一个数组和int 21 //说明: 22 //1.调用initArray函数 23 //2.传入了一个函数名getNextRandomValue(地址),需要使用函数指针来接收 24 initArray(myarray, 10, getNextRandomValue); 25 for ( i = 0; i < 10; i++){ 26 printf("%d\n", myarray[i]); 27 } 28 printf("\n"); 29 return 0; 30 }
指针使用的注意事项以及空指针:
关于第二点和第三点:
标签:arr,int,地址,printf,ptr,指针 From: https://www.cnblogs.com/MorningMaple/p/16773970.html