一个运行的进程内存空间分为四个区域,代码区,全局数据区,堆区和栈区。
代码区存放程序的执行代码;全局数据区存放全局数据、常量、文字量、静态变量;堆区存放动态内存,共程序随即申请使用;栈区存放函数里的局部数据;
指向代码区的函数的指针就是函数指针。
定义一个函数指针变量形式如下:
int (*fun) (int); --------------定义一个函数指针变量fun,这里不是声明
int g(int);
fun = g; //赋值
int (*fun) (int) = g; ---------也可以定义函数指针的同时初始化函数指针变量
为了简化函数指针变量的定义,我们通过typedef来定义一个别名。
typedef int (*Fun)(int);
Fun p;
p = g; //or p = &g;
函数名g不是函数指针,本来是不能直接赋值给函数指针p的。但是由于编译器在需要函数指针的地方如果是碰到了函数名,则会自动地将函数名转换为函数指针。
所以p = g也是正确的,但是最明确的写法应该是p = &g;将函数g的地址赋值给函数指针变量p。
既然函数名可以隐式地转换为函数指针,那么在需要函数名的地方编译器也支持将函数指针隐式地转换为函数名。就像int类型可以隐式转换为short,short也可以转换为int一样。
所以如下通过函数指针调用函数也是成立的:
p(int);
但是正规明确的写法应该是:
(*p)(int);
Tip:
函数名和数组名都不是指针,只不过在需要指针的地方是编译器自动转换为指针了。
当数组名在需要指针的地方,则被隐式地转换为指向数组第一个元素的指针;
如果是不需要数组的地方,数组名则不被转为为指针,仍然代表整个数组。
int a[10];
sizeof(a); ----这里不需要指针,a代表数组,表示10个int类型的整数,值为40
sizeof(*a); -----这里需要指针,a被隐式转换为指针指向第一个元素,所以一个元素的长度值为4