标题:指向函数的指针(续) - C语言
内容:前面写过《指向函数的指针 - C语言》,本文将在数组指针的基础上对函数的指针探究。
作者:MilkCu
数组名与数组名取地址
我们先来做个关于数组的小实验:
# include <stdio.h> int main(void) { int a[2] = {3, 4}; printf("a = %d\n", a); printf("&a = %d\n", &a); printf("a + 1 = %d\n", a + 1); printf("&a + 1 = %d\n", &a + 1); printf("*(a + 1) = %d\n", *(a + 1)); printf("*(&a + 1) = %d\n", *(&a + 1)); return 0; }
得到的结果意料之中,如下所示:
a = 2686744 &a = 2686744 a + 1 = 2686748 &a + 1 = 2686752 *(a + 1) = 4 *(&a + 1) = 2686752
由此分析,a表示的是数组的第一个元素的指针,&a表示的是数组的指针,(a + 1)表示的是数组的第二个元素的指针,(&a + 1)表示的没有意义的值。
我们得到结论:对于数组a[2],&a指的是指向数组的指针,a指的是指向数组第一个元素的指针,在指针类型上是有区别的。
指向函数的指针
我们再做个关于函数指针的实验:
# include <stdio.h> void fun(void) { printf("Hello.\n"); } int main(void) { printf("fun = %d\n", fun); printf("&fun = %d\n", &fun); printf("*fun = %d\n", *fun); printf("*&fun = %d\n", *&fun); printf("&*fun = %d\n", &*fun); printf("****fun = %d\n", ****fun); //printf("&&&&fun = %d\n", &&&&fun); //无法编译通过 printf("fun + 1 = %d\n", fun + 1); printf("*fun + 1 = %d\n", *fun + 1); printf("&fun + 1 = %d\n", &fun + 1); //printf("sizeof(fun) = %d\n", sizeof(fun)); //无法编译通过 //printf("sizeof(*fun) = %d\n", sizeof(*fun)); //无法编译通过 printf("sizeof(&fun) = %d\n", sizeof(&fun)); return 0; }
编译过程中,会产生如下警告:
E:\c\play\function.cpp In function 'int main()': 15 33 E:\c\play\function.cpp [Warning] pointer to a function used in arithmetic [-Wpointer-arith] 16 35 E:\c\play\function.cpp [Warning] pointer to a function used in arithmetic [-Wpointer-arith] 17 35 E:\c\play\function.cpp [Warning] pointer to a function used in arithmetic [-Wpointer-arith]
打印结果如下:
fun = 4199344 &fun = 4199344 *fun = 4199344 *&fun = 4199344 &*fun = 4199344 ****fun = 4199344 fun + 1 = 4199345 *fun + 1 = 4199345 &fun + 1 = 4199345 sizeof(&fun) = 4
分析一下,发现&fun指的肯定是函数的指针,而对于fun和*fun则根据情况而定。产生的警告则说明,函数的指针与其他类型(如整型等)的指针不同,不能进行加减运算。
(只是通过代码,感性分析,纯属个人见解)
实际上,函数名就代表了函数的地址,因此fun就是一个地址。这个跟数组非常类似,其名字就是指针常量,也即一个地址。
对函数名取地址,即&fun产生指向函数的指针,也可以看做是函数的地址。 因此fun和&fun结果一致。
而 *fun代表指向函数的指针,指向的是函数的地址。所以可以得到*fun = fun。
即:*fun=*(fun) = *(&fun) = fun
小结
在C语言中,函数本身不是变量,但可以定义指向函数的指针。这种类型的指针可以被赋值、存放在数组中、传递给函数以及作为函数的返回值等等。
函数作为参数传递给函数时,因为它们是函数,前面不需要加取地址运算符&。同样的原因,数组名前面也不需要&运算符。
(全文完)