首先我们要先明白一个概念,函数名是不是指针?也就是说一个函数名可不可以代表一个地址?以及什么是函数类型?
经过查找,函数名就是一个指针,但是意义是不一样的,如同于数组a[],a和&a其实都是一样的。当调用一个函数时,我们都是直接用函数名调用,或者说通过指针调用。
函数类型,在我理解,就是定义了一个函数应该返回什么样的类型,int?void?以及它的参数形式。
那么:
1,tpyedef自定义函数指针类型:看一个例子:
01 | #include <stdio.h> |
02 |
03 | typedef int (*fp_t)( char c); |
04 |
05 | int f0( char c) { printf ( "f0, c = %c\n" , c); return 0;} |
06 | int f1( char c) { printf ( "f1, c = %c\n" , c); return 1;} |
07 |
08 | int main() |
09 | { |
10 |
int ret; |
11 |
fp_t fp; //fp是一个指向一个函数类型(返回的是int,参数是char)的函数指针 |
12 |
13 |
fp = f0; |
14 |
ret = fp( 'a' );通过函数指针调用函数 |
15 |
16 |
fp = f1; |
17 |
ret = fp( 'x' ); |
18 |
return 0; |
19 | } |
2,typedef自定义函数类型:
例子:
01 | #include <stdio.h> |
02 |
03 | typedef int f_t( char c); |
04 |
05 | int f0( char c) { printf ( "f0, c = %c\n" , c); return 0;} |
06 | int f1( char c) { printf ( "f1, c = %c\n" , c); return 1;} |
07 |
08 | int main() |
09 | { |
10 |
int ret; |
11 |
f_t *fp; //f_t是函数类型,所以fp是指向此函数类型的指针 |
12 |
13 |
fp = f0; |
14 |
ret = fp( 'a' ); |
15 |
16 |
fp = f1; |
17 |
ret = fp( 'x' ); //函数指针调用此函数 |
18 |
return 0; |
19 | } |
typedef int mf(void);
int test1(void);
int test(mf *fp)
{
return fp();
}
int main(int argc,char * argv[])
{
printf("%d\n",test(test1));
exit(0);
}
int test1(void)
{
return 3;
}
在test函数的定义中,我们发现它需要一个参数,此参数是指向mf类型的函数的指针,而test1函数正好是mf类型的函数,而test1正好是这种函数的地址(函数名即是函数地址),故而可以把test1传递给test函数。
【typedef与#define】
【案例】
typedef int* Tpi;
#define int* Dpi;
Tpi p1,p2;
Dpi p3,p4;
问上述代码中定义的四个变量分别为什么类型?
【分析】
区分p1,p2,p3,p4四个变量的类型,首先要理解typedef和#define宏的区别,typedef是给已有的类型取别名,而#define只是简单的字符替换。于是上述代码等同于
int *p1,*p2;//typedef的作用
int *p3,p4;//#define的作用
也就是说p3被定义为了一个整型指针,而p4则只是整型。
5.typedef之const指针
【案例】
typedef string * pstr;
const pstr cpstr;
问上述代码中cpstr是一个怎样的指针?
【分析】
很多朋友,包括我自己在刚接触到时,第一反应是:cpstr被定义为一个指向const string对象的普通指针,原因很简单,置换一下string*与pstr的位置就得到
//这显然就是一个指向const string对象的普通指针
const string * cpstr;
然而,事不如人愿,cpstr的确切定义为:一个指向string类型的const指针。
看到这个答案,相比不少朋友稍显惊讶,我也如此,其中内因,且听我慢慢道来。
之所以出错,在于我们“置换一下就好了”,“置换”这个词不应该用在typedef,而该用在#define宏身上,typedef是定义了一个类型别名,定义的结果遵循任何正常定义的标准。那么这个typedef到底是怎么定义了一个const指针呢?
首先分析
const pstr cpstr;
这段代码定义了一个pstr类型的const cpstr,实际上就是
pstr const cpstr;
为了便于理解,就拿int定义来说
//二者等价,前者是习惯用法,后者是标准规定
const int ival = 0;
int const ival = 0;
既然理解了cpstr是一个const的pstr类型的对象,pstr是什么呢?pstr是string*,因此这样一来,就成了cpstr是一个const的string*类型的对象,也即cpstr是一个指向普通string的const指针。
【总结】
本次误解主要源于大家认为typedef等同于#define宏定义,以为简单替换字符就可以了。实则不然。以后见到这样的定义,最简单的办法就是从定义该变量的地方入手
typedef string * pstr;
const pstr cpstr;
按步骤(熟练了就很快了)思考:
①cpstr是一个类型为 pstr 的常量
②pstr 是什么?
③pstr 是 string*
④所以,cpstr是一个类型为 string* 的常量,也即 string *const cpstr