指针理解——指针数组数组指针指针函数函数指针

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 }
View Code

运行结果:

技术分享图片

根据运行结果,很多人就会得出“数组名就是首元素的地址”这样错误的结论。见代码

技术分享图片
 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 }
View Code

运行结果:

技术分享图片

如果 “数组名就是首元素的地址” 结论属实,那么数组名的大小就是一个指针的大小。事实上,数组名代表整个数组空间。只不过数组名内部的值刚好是首元素的地址,知道首元素的地址,再知道数组长度就可以操纵数组。

数组指针、指针数组

  数组名代表真个数组空间,那么,对数组名取地址,即就是在对整个数组取地址,则数组的地址自然要用指向数组的指针才能接收,所以,必须定义指向数组的指针类型,即为数组指针。见代码

技术分享图片
 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 }
View Code

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 }
View Code

函数指针、指针函数

函数指针

函数指针,首先它是一个指针,只不过,指针所指向的类型是函数,它是“指向函数的指针”的简称

技术分享图片
 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 }
View Code

一般来说,我们调动函数往往是通过函数名来进行调动,例如情形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 }
View Code

正确写法

技术分享图片
 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 }
View Code

 但是这种代码写出来太难理解了,可以使用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 }
View Code

 

以上是关于指针理解——指针数组数组指针指针函数函数指针的主要内容,如果未能解决你的问题,请参考以下文章

指针,数组指针,指针数组,函数指针解析

指针,数组指针,指针数组,函数指针解析

C语言进阶笔记深入了解进阶指针

C语言进阶笔记深入了解进阶指针

C语言进阶笔记深入了解进阶指针

C语言进阶笔记深入了解进阶指针