0. 通过函数指针调用函数时,函数指针变量前到底加不加星号。首先以例子说明。
#include <stdio.h>
typedef void (*TPFun)(void);
void syr(void)
{
printf("hello world!\n");
}
int main(int argc, char *argv[])
{
TPFun pFun;
int *Addr;
printf("%d\n",syr);
pFun = (void(*)(void))(4198760);//这里须保证地址与上面打印出的地址一致
printf("The 1st call...\n");
syr();
printf("The 2nd call...\n");
(*syr)();
printf("The 3rd call...\n");
(**syr)();
printf("The 4th call...\n");
(pFun)();
printf("The 5th call...\n");
(*pFun)(); printf("The 6th call...\n");
(**pFun)();
printf("The 7th call...\n");
((void(*)(void))(4198760))();
printf("The 8th call...\n");
(*((void(*)(void))(4198760)))();
printf("The 9th call...\n");
(*(*((void(*)(void))(4198760))))();
printf("\n\n\n");
getchar();
return 0;
}
}
可以看到不论加不加星号,加几个星号,都可以正常调用函数,甚至只要知道函数地址,也可以用立即数调用。到底是为什么呢?
1. 首先来弄明白C语言的指针问题。
#include <stdio.h>
int main(int argc, char *argv[])
{
unsigned int a=1234;
unsigned int *pint = &a;
printf("*pint=%d\n",*pint);
printf("pint=%d\n",pint);
printf("&pint=%d\n",&pint);
getchar();
return 0;
}
可以得到
变量 | 地址 | 内容 |
a | 1245064 | 1234 |
pint | 1245060 | 1245064 |
变量a的地址为1245064,指针变量pint的内容是a的地址,即为1245064。可以由此看出对应关系。
2. 分析:每加一个星号,代表取值,那为什么加几个星号都可以呢?
推算,函数名就是地址,而函数名对应的地址里存放的内容仍然是函数的地址,所以无论取几次星号,结果都一样。但是考虑到函数入口应该是函数主题的内容,实际情况是什么样的?本人对DSP的编程环境比较熟悉,这里以CCS进行了分析,对与c语言相关的汇编代码进行分析。定义了函数void f(void);并定义了void (*Pf)(void);函数指针,下图是定义的函数f的汇编代码。可以看到定义的函数入口地址为0x009597,而函数名称对应的标号对应的地址也为0x009597(核心解释)。所以,对于0x009597地址取值结果还是0x009597,再次取值仍然是0x009597。函数指针Pf的地址为0x000406,Pf的内容是0x009597,即Pf=0x009597,f的地址也为0x009597。所以
f();
(*f)();
Pf();
(*Pf)();
(**Pf)();
的结果是一致的。