能力值:
( LV2,RANK:10 )
|
-
-
2 楼
睡前人工置顶
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
管它什么指针 还不是个DWORD
所以这样也可以
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
#include <windows.h>
#include <stdio.h>
int main()
{
HINSTANCE LibHandle;
FARPROC farproc;
LibHandle = LoadLibrary("user32");
printf("msvcrt LibHandle = //x%x\n", LibHandle);
farproc=GetProcAddress(LibHandle,"MessageBoxA");
printf("system = //x%x\n", farproc);
return 0;
}
这样也可以通过成功获取函数地址,但是我就是不懂 1楼那个 函数指针 到底是怎么回事
|
能力值:
(RANK:350 )
|
-
-
5 楼
编译正确=正确稳定运行?
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
编译当然正确,都是DWORD嘛,呵呵,ls正解,编译正确甚至在你的机器上运行正确并不能代表程序就是正确的。
至于函数指针,很好理解,函数的名字指代的就是函数的首地址(就像数组的名字一样),调用一个函数可以通过函数的名字来调用func(1,2),那自然也可以用一个指向函数的指针的来调用这个函数(*pFunc)(1,2),这两者是一样的,就像下面:
#include<iostream>
using namespace std;
typedef void(*pFunc)(int);
void func(int a)
{
cout << a << endl;
}
int main()
{
func(7); //这总没问题吧
pFunc pf = func;
(*pf)(11); //函数指针
cout << func << endl;
cout << pf << endl; //这两者显然是一样的
return 0;
}
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
首先,你的那段代码是有错误的...
函数指针本质上也是指针,内容为函数的首地址。
GetProcAddress 的返回值类型为 FARPROC
因为 FARPROC 和 MYPROC 不兼容,所以你在赋值时使用了强制转换...
声明只是在编译阶段起到检查作用,所以不会阻止你进行强制类型转换,但当你使用时:
(*ProcAdd)(...);
你便会发现只有输入单个 LPTSTR 类型时才能编译通过,但运行时是肯定会崩溃的~
因为实际上函数接受4个参数,这就说明使用函数指针的危险性,关键是要理解函数指针的正确声明。
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
依然没得到...
3L 不管那一段代码编译后,获取的地址都是一样的 正确的.
我就是想问那个函数指针到底是怎么样事
|
能力值:
( LV2,RANK:10 )
|
-
-
9 楼
6楼
你那个例子
既然pf指向func函数的首地址
下面一句何必这样写了?(*pf)(11); 改成pf(11); 直接调用pf指向的地址函数 不是更简洁?
|
能力值:
( LV2,RANK:10 )
|
-
-
10 楼
你调用MessageBox的时候可以这样写:
push
push
push
push
call MessageBox
这就好比高级语言里写MessageBox(NULL,offset szText,offset szCaption,MB_OK),这是我们常用的调用方式(C里可没有offset,哈哈)。
你也可以通过fp = (FARPROC)GetProcAddress(LoadLibrary("user32.dll"),"MessageBoxA")来获得MessageBoxA的地址,然后这样调用:
push
push
push
push
call fp
这就好比是(*fp)(NULL,offset szText,szCaption,MB_OK),在高级语言的角度来看,两者是不同的,但是在汇编的角度来看,两者其实是一回事,因为函数的名字本身就存储着函数的地址,函数的名字本身就是一个函数指针,我们调用函数的时候用谁都一样,都是用的函数的地址。只是函数名字存储函数地址这个事实被编译器给隐藏了,我们平时也不在意。
返回值类型 函数名字(参数)
返回值类型 函数地址(参数)
两者是一回事~
|
能力值:
( LV2,RANK:10 )
|
-
-
11 楼
函数指针在x86平台长度是4字节,其本质上还是指针,指向的内容为函数的首地址。
申明一般如下:
返回值类型 (*变量名)(形参列表);
形参列表是可选的。
例如:
void (*ProcAdd)(LPTSTR);
声明了名为ProcAdd的指针,他指向的函数接受1个LPTSTR类型参数,无返回值。
|
能力值:
( LV2,RANK:10 )
|
-
-
12 楼
11楼
我说的不是 函数指针声明;
我说
ProcAdd=(MYPROC)GetProcAddress(LibHandle,"MessageBoxA"); //这里不懂
ProcAdd=(void (*)(LPTSTR))GetProcAddress(LibHandle,"MessageBoxA"); //这里不懂
为什么这样可以强制转换
|
能力值:
( LV2,RANK:10 )
|
-
-
13 楼
额,这我倒没想过,呵呵,一直用(*pf)(11)写习惯了……不知有区别没,貌似没有,呵呵。
建议你直接从汇编的角度的理解吧,高级语言里的函数调用不过就是
push eip
jmp 函数地址
这个函数地址你爱怎么获得怎么获得,用函数名字也好,用你自己弄的函数指针也罢,你直接写出来这个地址都行,也就是说只要地址是同样的,你爱咋写咋写
|
能力值:
( LV2,RANK:10 )
|
-
-
14 楼
这是C语言的规定……这样写就是进行强制类型转换的……没有为什么……
|
能力值:
( LV2,RANK:10 )
|
-
-
15 楼
晕,我知道你为什么不懂了,是因为形式的原因……
ProcAdd=(void (*)(LPTSTR))GetProcAddress(LibHandle,"MessageBoxA");
你不知道为什么用(void (*)(LPTSTR))来进行强制类型转换是不是?
因为你写的是 typedef void(*MYPROC)(LPTSTR) ,这样写那么就意味着你定义了一个新的数据类型,叫做MYPROC。去掉typedef,去掉你定义的类型名MYPROC,就剩下void(*)(LPTSTR)了,所以你新定义的这个数据类型就是void(*)(LPTSTR)类型的,所以强制类型转换时要写成(void(*)(LPTSTR))这种奇怪的样子……
而你写了typedef ……之后,(void (*)(LPTSTR))也就是MYPROC了,俩是一样的,所以你也可以用(MYPROC)来进行强制类型转换。
|
能力值:
( LV2,RANK:10 )
|
-
-
16 楼
14楼
你的意思是?
GetProcAddress把它强制转换成MYPROC? GetProcAddress他是有返回值的,MYPROC定义是他是void 这样也可以强制?
ProcAdd=(MYPROC)GetProcAddress(LibHandle,"MessageBoxA"); //这里 既然你说强制转换成MYPROC ,那应该没反正值啊 为什么ProcAdd 还可以接收返回值?
|
能力值:
( LV2,RANK:10 )
|
-
-
17 楼
C语言同时给了程序员最大的编程自由度和严格的类型检查机制。
FARPROC定义如下:
typedef int (__stdcall *FARPROC)();
明显与MYPROC定义不兼容,显示的强制转换是因为编译器希望确认这的确是你希望要做的。
正因为如此,显示的强制类型转换是不安全的。
|
能力值:
( LV2,RANK:10 )
|
-
-
18 楼
15楼
typedef 简化代码我知道啊!
我在一楼写了2个版本的.
回答我16
楼问题就行了
|
能力值:
( LV2,RANK:10 )
|
-
-
19 楼
终于懂你的意思了,强制转换的是返回值,也就是把FARPROC转成MYPROC啊......
注意优先级的问题
|
能力值:
( LV2,RANK:10 )
|
-
-
20 楼
不是void,看我在15L的解释,就好像 typedef bool BOOLEAN;一样,以后需要用bool的地方也就可以用BOOLEAN来代替了。
同理 typedef void(*MYPROC)(LPTSTR),那么以后需要用 void(*)(LPTSTR)的地方也就可以用MYPROC代替了。
PS:为了这个分我可真是尽心竭力了……还差3分就够钱买个邀请码了……
|
能力值:
( LV2,RANK:10 )
|
-
-
21 楼
你15楼那个回答我 知道啊!
程序原版是 typedef 定义了函数指针类型
我在原版程序改成了ProcAdd=(void (*)(LPTSTR))GetProcAddress(LibHandle,"MessageBoxA"); 这种奇怪的格式.
|
能力值:
( LV2,RANK:10 )
|
-
-
22 楼
我想问的 GetProcAddress(有返回值)强制转换成 无返回值的 函数指针 这样可以?
还有就是 就算转换成功 他应该没返回值啊 怎么可以用ProcAdd接受返回值
就是这样
|
能力值:
( LV2,RANK:10 )
|
-
-
23 楼
[QUOTE=wonderu;762139]终于懂你的意思了,强制转换的是返回值,也就是把FARPROC转成MYPROC啊......
注意优先级的问题[/QUOTE]
没有强制转换GetProcAddress啊
是返回的FARPROC类型的指针变量......
|
能力值:
( LV2,RANK:10 )
|
-
-
24 楼
不知你到底想知道什么……囧……
如果不是专门问函数指针问题的话,建议你直接按M$的写法写就是了:
FARPROC WINAPI GetProcAddress(
__in HMODULE hModule,
__in LPCSTR lpProcName);
直接强制转换成FARPROC,也不用管其它的了……
或者
FARPROC uAddr;
(FARPROC &) uAddr = GetProcAddress(LoadLibrary("user32.dll"),"MessageBoxA");
自己看着写呗,只要没犯原则性错误就是了……
|
能力值:
( LV2,RANK:10 )
|
-
-
25 楼
19楼wonderu
终于看到了!我问的就是这个返回值
你说下吧!
ProcAdd=(void (*)(LPTSTR))GetProcAddress(LibHandle,"MessageBoxA"); 这个到底是怎么执行的,说明白点 我1楼倒数第二行开始也假设过!
|
|
|