一. 数组指针和指针数组
- 数组指针:指向数组的指针,例如:char (*p)[3];
a.概念:
保存数组的地址的指针变量,称为指针数组。
b.例如:
char c[3]; //数组c是有三个char型元素的数组
p=&c; //&c表示的是整个数组的地址,数组指针p指向的这个数组 - 指针数组:由多个指针变量构成的数组,例如:char *p[3];
a.概念:
数组元素类型为指针类型的数组称为指针数组,该数组中每个指针元素类型为char *类型。
b.例如:
char c1,c2,c3;
p[0]=&c1;
p[1]=&c2;
p[2]=&c3; - 辨析
a.(*p)[3]
与*p[3]
不加括号的区分:*p不加括号的话,由于[ ]
的优先级高于*
,因此,数组名p先于[ ]
结合,构成了一个数组形式,然后该数组的每个元素再与*
结合,说明每个数组元素是指针类型。而加了括号后p先于*
结合,说明该变量是指针类型的,然后该指针p又与[ ]
结合,说明该指针变量p是指向数组结构类型的指针变量。
b.数组指针与指针数组短语辨析:这两个名词可以从后面两个词来区分,数组指针本质上就是一个指针,不过该指针是指向整个数组首地址的指针,指针数组本质上就是一个数组,这个数组的每个元素是指针类型的。
二.函数指针和指针函数
- 函数指针:指向函数的指针,例如:int (*p)(char)
a.概念:
保存函数入口地址的指针变量,称为函数指针。
b.例如:
定义一个函数,int fun(char);
函数p所指向的地址为fun或&fun。
函数名fun本质上就是一个地址常量。
p=fun或p=&fun
。说明函数指针p指向了fun函数。 - 指针函数:返回指针类型的函数,例如: char *p(char)
例如:char *str(char *c){ return c; }
- 辨析
a.(*p)(char)
与*p(char)
不加括号的区别:*p不加括号的话,()
的优先级比*
高,然后括号里又是一个函数参数类型,说明该p是一个函数名,括号与p结合。我们知道函数是都是有返回值的,所以这里的*p(char)
实际变成的是这个函数的返回值,相当于*p(char)
–>*( p(char) )
–>函数p返回的值,该值是一个指针类型
。而(*p)(char)
两边都加了括号,按照括号优先级的结合方向(自左至右),(*p)
说明变量p是一个指针变量,而(char)
表示的是一个函数的参数,说明该函数参数的左边的变量p是该函数的名称,又因为之前声明了该变量p是一个指针变量,说明了该函数是一个指向相同输入型参数和相同返回类型值的函数的函数指针。
b.函数指针与指针函数短语辨析:指针函数是指返回值是指针的函数,即本质是一个函数,函数指针是一个指向函数的指针,本质上就是一个指针。
三.函数指针数组
-
由函数指针构成的数组,例如: int (*p[2])(char)
数组中元素为函数指针类型,由这些函数指针类型的元素构成的数组称为函数指针数组。int func1(char) { ... } int func2(char) { ... } p[0]=func1; p[1]=func2;
-
辨析:
在(*p[3])(char)
中都有括号,同级()
的结合方向为自左向右,也就是先声明p为一个数组指针,然后(char)
表示的是一个函数的参数,所以左边的变量p是该函数的名称,又因为该变量p为数组指针类型的变量,说明了p是指向多个相同输入类型和返回类型的函数指针数组。函数指针数组本质上还是一个数组,但该数组保存的值与我们平常的值不同,保存的是多个函数名的地址。
三.扩展:
typedef void (*handler)(int);//等价于typedef (*)(int) handler
handler func(int b,handler hd) //定义了一个函数func,该函数第二个参数hd为函数指针类型
{ ... //该函数返回的是一个函数指针类型的地址,也就是一个地址,即
} //函数func是一个指针函数