首页 新闻 会员 周边

函数指针指向及数组首地址问题

1
[已解决问题] 解决于 2011-12-19 01:13

首先看小段代码:

#include <stdio.h>
int func()
{
printf("in func\n");
}
int (*pfunc)();
int main()
{
printf("func = %x\n",func);
pfunc = func;
printf("*pfunc = %x\n",*pfunc);
printf("pfunc = %x\n",pfunc);
getchar();
}

打印结果:

func = 4012d0
*pfunc = 4012d0
pfunc = 4012d0

不理解的是*pfunc和pfunc值为什么是一样的呢?

请高手帮帮忙!

 

另外关于指针和数组还有一点不明:

对于一个数组

int array[10];

为什么 array&array 的值是一样的呢?

期待高手的解惑!

WangCT的主页 WangCT | 初学一级 | 园豆:186
提问于:2011-12-16 07:04
< >
分享
最佳答案
1

现回答你的函数指针疑问。

我的思路是通过反汇编来剖析编译器在背后为我们做了些什么。

    unsigned long pfuncAddr = (unsigned long)&pfunc;
01386E2E  mov         dword ptr [pfuncAddr],offset pfunc (139051Ch)  
printf("pfunc addr = %x\n", pfuncAddr);
01386E35 mov esi,esp
01386E37 mov eax,dword ptr [pfuncAddr]
01386E3A push eax
01386E3B push offset string "pfunc addr = %x\n" (138DAACh)
01386E40 call dword ptr [__imp__printf (13914D8h)]
01386E46 add esp,8
01386E49 cmp esi,esp
01386E4B call @ILT+1025(__RTC_CheckEsp) (1381406h)
pfunc = func;
01386E50 mov dword ptr [pfunc (139051Ch)],offset func (1381483h)
printf("*pfunc = %x\n", *pfunc);
01386E5A mov esi,esp
01386E5C mov eax,dword ptr [pfunc (139051Ch)]
01386E61 push eax
01386E62 push offset string "*pfunc = %x\n" (138DAC4h)
01386E67 call dword ptr [__imp__printf (13914D8h)]
01386E6D add esp,8
01386E70 cmp esi,esp
01386E72 call @ILT+1025(__RTC_CheckEsp) (1381406h)
printf("pfunc = %x\n", pfunc);
01386E77 mov esi,esp
01386E79 mov eax,dword ptr [pfunc (139051Ch)]
01386E7E push eax
01386E7F push offset string "pfunc = %x\n" (138DA14h)
01386E84 call dword ptr [__imp__printf (13914D8h)]
01386E8A add esp,8
01386E8D cmp esi,esp
01386E8F call @ILT+1025(__RTC_CheckEsp) (1381406h)

以下代码是为了获取pFunc函数指针变量地址,打印的结果是139051Ch,从这个事实可以判断,pfunc是一个全局变量。

    unsigned long pfuncAddr = (unsigned long)&pfunc;

我们在回到反汇编后的代码:

01386E5C  mov         eax,dword ptr [pfunc (139051Ch)]  
01386E79  mov         eax,dword ptr [pfunc (139051Ch)]  

这里有两个细节需要注意:

1, 代码pfunc 和 *pfunc反汇编后是一样的。

      从这点我们可以知道,编译器在编译期就把pfunc 等同于 *pfunc。

2, dword ptr [pfunc (139051Ch)] 都是取地址139051Ch内容,而这个值就是我们前面取到的值。

同样的方法也可以解决你数组名的疑问。


胡屯 | 小虾三级 |园豆:714 | 2011-12-16 12:20
其他回答(3)
1

先回答指针与数组名称的问题,编译器对于指针和数组名称的处理是不同:指针是一个变量,因此编译器会给其申请地址空间,而编译器把数组名看成是一个符号,不会给其分配地址空间,它记录的仅仅是array[0]的地址而已。因此,array和&array的值是一样的,都是array[0]的地址。

关于数组名称和指针变量的区别,可以看下链接中的专题探讨

http://www.cnblogs.com/welkinwalker/archive/2011/09/07/2170165.html

然后再来说,函数指针的问题:
声明了函数指针后,即iint (*pfunc)(); 编译器并未给其分配空间,而是将其当作符号来处理,记录下函数堆栈的首地址,你可以在对其赋值之前,打印*pfunc和pfunc的值,你可以看到输出都为0,因为没有将任何函数堆栈地址给它赋值;实际上函数名是一种隐式指针,而你在打印pfunc的值时,编译器会将其按照*pfunc对待并打印。因此*pfunc和pfunc的值都一样;

朝雾之归乡 | 园豆:71 (初学一级) | 2011-12-16 09:11
0

(1)、func = 4012d0 这个好理解了吧,就是func入口的地址

(2)、*pfunc = func = 4012d0 这个关系你懂的了。*pfunc的意义是pfunc所指向的函数入口地址为4012d0

(3)、pfunc = 4012d0 这个是因为pfunc是一个指针变量,也相当一个无符号的整型变量,里面存放着一个函数的入口地址。这个函数的地址就是 4012d0,这一点上面已经验证了。

(4)、你想要的,且有所不同的应该是这个东西 &pfunc  。变量pfunc的地址。

(5)、array 与 &array 。在编译器看来array是一个数组名,也即是一段内存的起始地址。而&array是显示地获得array数组的起始地址,和&array[0]是一样的。

 


泛黄的梦 | 园豆:205 (菜鸟二级) | 2011-12-16 09:20
0

都被你们回答了。。。。

会飞的机器猫 | 园豆:86 (初学一级) | 2011-12-16 09:38
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册