指针理解——指针数组数组指针指针函数函数指针
Posted kelamoyujuzhen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了指针理解——指针数组数组指针指针函数函数指针相关的知识,希望对你有一定的参考价值。
一个存在已久的谣言
源码
1 #include <stdio.h> 2 int main() 3 { 4 int ar[10] = { 1,2,3,4,5,6,7,8,9,10 }; 5 printf("&ar[0]=%p ",&ar[0]); 6 printf("ar=%p ", ar); 7 printf("&ar=%p ", ar); 8 getchar(); 9 return 0; 10 }
运行结果:
根据运行结果,很多人就会得出“数组名就是首元素的地址”这样错误的结论。见代码
1 #include <stdio.h> 2 int main() 3 { 4 int ar[10] = { 1,2,3,4,5,6,7,8,9,10 }; 5 printf("&ar[0]=%p ",&ar[0]); 6 printf("ar=%p ", ar); 7 printf("&ar=%p ", ar); 8 printf("sizeof(ar)=%d ", sizeof(ar)); 9 printf("sizeof(&ar[0])=%d ", sizeof(&ar[0])); 10 getchar(); 11 return 0; 12 }
运行结果:
如果 “数组名就是首元素的地址” 结论属实,那么数组名的大小就是一个指针的大小。事实上,数组名代表整个数组空间。只不过数组名内部的值刚好是首元素的地址,知道首元素的地址,再知道数组长度就可以操纵数组。
数组指针、指针数组
数组名代表真个数组空间,那么,对数组名取地址,即就是在对整个数组取地址,则数组的地址自然要用指向数组的指针才能接收,所以,必须定义指向数组的指针类型,即为数组指针。见代码
1 #include <stdio.h> 2 int main() 3 { 4 int ar[10] = { 1,2,3,4,5,6,7,8,9,10 }; 5 int *p = ar; 6 7 /*下面是错误代码 8 int **p = &ar;*/ 9 10 //正确写法 11 int(*pp)[10] = &ar; 12 getchar(); 13 return 0; 14 }
int *p = ar; 这一句OK,相当于int *p = ar+0; ar+0是数组下标为0的元素(首元素)的地址
int **p = &ar; ar是代表10个int类型大小的变量,与int**类型不符
int(*pp)[10] = &ar;正确写法,定义数组指针pp,该指针类型是 int (*)[10],指向int [10]类型
数组指针、指针数组重点在于后两个字。即数组指针本质上是指针,指针数组本质上是数组。这是字面上理解,代码角度怎么区分呢?
int ar[10] = { 1,2,3,4,5,6,7,8,9,10 }; int(*p1)[10] = &ar; //数组指针 int* p2[3]; //指针数组
变量(这里是p1,p2)与[ ]优先结合,所以int* p2[3];是指针数组,是一个数组。 要想变成指针,需要使用 ()强制优先结合指针。
总结:
数组指针:
首先它是一个指针,它指向一个数组,在32位系统下永远是占4个字节,至于它所指向的数组占多少字节是不知道的,它是“指向数组的指针”简称
对于数组指针,强调的是指针的概念,只不过,指针的能力是用来指向数组类型的,并且其方括号中的数字一定,例如:int (*p)[10],p就是指向数组的指针,其中p指针规定了只能指向整形的数组,并且数组大小只能是10个整形空间,不能多也不能少,多之少之都会认为其指针的能力与指向的实体不符。
指针数组:
指针数组,首先它是一个数组,数组的元素都是指针,数组占多少字节由数组本身决定,它是“储存指针的数组”的简称。
对于指针数组,强调的是数组的概念,只不过,数组所保存的类型是指针罢了,其地位跟普通的数组没有什么区别,都是数组,只不过是大家保存的类型不同而已,因此,我们美名其曰:保存指针的数组就称其为指针数组, 例如:int *p1[10]
指针数组最典型的例子就是main函数:int
main(
int
argc,
char
*argv[]) 第二个参数是一个字符串指针数组
1 #include <stdio.h> 2 int main() 3 { 4 int ar[3] = { 1,2,3 }; 5 //数组指针指向ar 6 int (*p)[3] = &ar; 7 //指针数组 8 int* q[3] = {&ar[0],&ar[1],&ar[2]}; 9 char* pstr[] = { "Hello","halo","nihao" }; 10 getchar(); 11 return 0; 12 }
函数指针、指针函数
函数指针
函数指针,首先它是一个指针,只不过,指针所指向的类型是函数,它是“指向函数的指针”的简称
1 #include <stdio.h> 2 int Max(int a, int b) 3 { 4 printf("%d ", a > b ? a : b); 5 return a > b ? a : b; 6 } 7 8 //函数指针 9 int(*pfun)(int, int); 10 11 void main() 12 { 13 //情形1 14 Max(1, 2); 15 16 //情形2 17 int(*pfun)(int, int); 18 pfun = &Max; 19 (*pfun)(1, 2); 20 21 //情形3 22 pfun = Max; 23 pfun(1, 2); 24 25 getchar(); 26 }
一般来说,我们调动函数往往是通过函数名来进行调动,例如情形1,由于指针强悍与无所不能,只要你能表示出来的,指针都可以想办法指向,因此,通过指针来调动函数就显得很自然了,我们把能够指向函数的指针称为函数指针,例如情形2,把Max函数的地址赋给了pfun函数指针,在调动时先取值,然后再调动函数,这是一种标准的做法,事实上,由于函数名就是函数的入口地址,本身也充当了地址,因此,我们可以简化程序,例如情形3,由于指针所指之物为函数,因此它的调动就行如直接运行函数类似了,但是,心里的清楚,情形3的做法实际是情形2的简写过程。
注意,一般指针都有其加1的能力,但是,函数指针不允许做这样的运算。即pfun+1是一个非法的操作。
指针函数
指针函数,首先它是一个函数,只不过,函数所返回的类型是指针类型,它是“返回指针类型的函数”的简称。 我们把返回指针类型的函数称其为指针函数,那就意味着只要返回值为指针,无论是什么类型的指针,都有资格称为指针函数
//指针函数,返回整形指针 int* fun(int a, int b) { return 0; }
像这种,函数fun,参数是(int a, int b),返回值是int* 。这种比较明显
如果返回值是函数指针呢?
先看一种错误的写法。对于VS2012以后的IDE,这种代码写得时候直接显示红色?,根本编译不过
1 #include <stdio.h> 2 int Max(int a, int b) 3 { 4 printf("%d ", a > b ? a : b); 5 return a > b ? a : b; 6 } 7 8 //指针函数,返回函数指针。但是这种写法是错误的 9 int(*) (int,int) func(int a, int b, int(*FUN)(int, int)) 10 { 11 printf("max value=%d ", FUN(a, b)); 12 return FUN; 13 } 14 15 void main() 16 { 17 func(1, 2, Max); 18 getchar(); 19 }
正确写法
1 #include <stdio.h> 2 int Max(int a, int b) 3 { 4 printf("%d ", a > b ? a : b); 5 return a > b ? a : b; 6 } 7 8 //函数指针 9 int(*pfun)(int, int); 10 11 12 //func这个函数参数是(int a, int b, int(*FUN)(int, int)),返回值是个指针,这个指针是int (*) (int, int)型函数指针 13 int(*func(int a, int b, int(*FUN)(int, int))) (int, int) 14 { 15 printf("max value=%d ", FUN(a, b)); 16 return FUN; 17 } 18 19 void main() 20 { 21 func(1, 2, Max); 22 getchar(); 23 }
但是这种代码写出来太难理解了,可以使用typedef简化代码
1 #include <stdio.h> 2 int Max(int a, int b) 3 { 4 printf("%d ", a > b ? a : b); 5 return a > b ? a : b; 6 } 7 8 //将函数指针定义成类型 9 typedef int(*pfun)(int, int); 10 11 12 //func这个函数参数是(int a, int b, int(*FUN)(int, int)),返回值是个指针,这个指针是int (*) (int, int)型函数指针 13 //int(*func(int a, int b, int(*FUN)(int, int))) (int, int) 14 pfun func(int a, int b, pfun FUN) 15 { 16 printf("max value=%d ", FUN(a, b)); 17 return FUN; 18 } 19 20 void main() 21 { 22 func(1, 2, Max); 23 getchar(); 24 }
以上是关于指针理解——指针数组数组指针指针函数函数指针的主要内容,如果未能解决你的问题,请参考以下文章