unsigned int len
char threadbuf(1024)*((long*)threadbuf)=len
据我所掌握的C语言,运算符*是用来访问以(long*)threadbuf为地址的存贮区域。可具体到VB语言,我就不知道如何去处理了。后面还有一条语句和这句类似:
unsigned long len=*((unsigned int*)threadbuf)我实在不明白,C语言如此处理的目的何在。
在下才学疏学浅,请各位指正。
char threadbuf(1024)*((long*)threadbuf)=len
据我所掌握的C语言,运算符*是用来访问以(long*)threadbuf为地址的存贮区域。可具体到VB语言,我就不知道如何去处理了。后面还有一条语句和这句类似:
unsigned long len=*((unsigned int*)threadbuf)我实在不明白,C语言如此处理的目的何在。
在下才学疏学浅,请各位指正。
解决方案 »
- 失恋,散分,无须多言
- 向各位求援????各位进来看看能不能帮忙一下。
- 关于FSO对象的两个问题,MoveFolder和WriteLine/Write操作时出错[代码见帖内]!!!
- 如何判断数据库是否连接正常
- vb中有没有方法能够在程序运行时删除自身?
- 纠正语句毛病
- 关于网络编程的问题!!!一个广播的问题,进来看看!1在线
- 怎样将几个项目文件形成一个项目程序组
- 如何让win2K关机?别人写过这方面的文章,不过小弟太莱,没有看懂:D
- 如何使用vb在98的ctrl alt del组合键里隐藏自己的程序?请正确理解我的本意
- 成功搞定了VB的全局HOOK!!!谢谢提供资料的那个家伙
- 用 VB 编写的 DLL,找不到入口?!!
访问需要用copymemory之类的API
如:
int a
则:*(&a)=a
那么:可不可以说:*((long*)threadbuf)=len就等同于threadbuf=len
不知道对不对,请诸位相助。
c是强制类型检查,对于基本数据类型,
这句恐怕无法通过编译
反过来赋值可以做自动转换
而且threadbuf是一个指针,不能这样赋值
vb没有指针类型,指针在32位机长度固定4字节
但*threadbuf则长1字节,在vc里,做一个buffer
实际上它可以用BYTE类型
只是个宏定义,可加强可读性
这个强制类型转换就是在强制*threadbuf的存储长度
但实际上在新的c++标准里,这是不被推荐的方法,因为这个安全隐患
不过也是c的效率所在,如果基础好一点你会发现这真的是很方便
如果高不清楚,你还是好好读读c吧
threadbuf本身是一个字节数组,而非指针,
(long*)threadbuf才是一个long型的指针变量,
而*这个运算符访问的不就是指针所指向的那个内存区域的值吗?
而(long*)threadbuf指针指向的内存就应该是threadbuf数组的首字节所在的位置,即:threadbuf(0).
所以,我认为:threadbuf(0)=len是没错的。
不知道对不对,请诸位指正。
threadbuf(0 1 2 3)= len目的不清楚,至少可以不用乘除转换了
vb一样可以,不过麻烦的很
我觉得你如果感兴趣真的该看看c
数组名就是一个指针常量,这是c语言很基本的知识
否则,(long*)threadbuf这样的运算(在c里*和)都是运算符)就是非法的
这么说没有别的意思,我觉得你要真的想搞明白不如自己看一看c
也不用很深,看明白谭浩强那本书就成
(怕是看完你就来了兴趣,那样可以看看c++primer,128元,但绝对物有所值)
这要比你在这里找人从头解释,甚至找不懂的人一起猜,要来的直接
看看c也绝对不亏,很多机理性的东西和汇编都是一致的
会对程序设计中概念的理解很有帮助,c语言自身的逻辑完备性真的是很优美
(long*)threadbuf和threadbuf指向的内存就是数组的首字节,但应该说他们的值等于
&threadbuf(0),而不是threadbuf(0)
二者的区别在于数据类型不同,前者在做*运算时取4字节的整数,后者取1字节整数,在.net中好像有不同,前者要取8字节整数,相当于vc6中使用__int64*
threadbuf(0)=len是有问题的,赋值运算符的左值只有1字节,而右值4字节,在某些编译器可以通过编译,但也会警告可能有数据损失,你可以试试,严格说应该是不能通过编译的。vb除外。
多谢您的指正。
我是因为时间紧,所以到这个论坛来,想快速解决问题。
对C语言中的指针也是恶补了一下,并没有完全弄明白。
看来这样真的不行。
我现在就去看谭SIR的书。
再次感谢你。
只是他说得太简单了,你要是没把概念弄懂可能一下子不明白
vb6有3个函数,用来取地址
varptr
strptr
objptr
分别是变量、字符串、对象
然后利用vb一般声明为copymemory的那个函数,拷贝4字节的整型数据到相应内存空间即可
可用long来存储得到的地址,每次加4切换到下一个long的空间
但事实证明,其实在vb里,copymemory的速度比vb自身的=赋值要慢(其实也是可想而知的,一个是函数调用,一个是几条mov指令),
如果可能你最好研究一下代码,其实程序不必直译,看看可不可以把那个数组定义为相应长度long的,对于我们的机器,本来操作long就比较快
当然,还要看看你程序的整体效果,怎样比较好。
没有下标的数组名就是一个指向该数组第一个元素的指针,
前一个将char* 转成 long*
后一个将 char* 转成 (unsigned int*)而VB中的变量类型转换对比C语言工具是很罗嗦了很多////
谢谢goater(goater)
关于VB中变量指针,讲的十分清楚。////
另外补充一个在VB中使用函数指针的
以下是摘录于VB5 Onlinehelp 的文章
"熟悉 C 语言的程序员一定会熟悉函数指针的概念。对于不熟悉 C 语言的读者,有必要对此进行一番解释。函数指针是一种约定,程序员可以用它将一个自定义的函数的地址作为参数传递到另一个函数。后面一个函数可以不是自己编写的,但是已经进行了声明,所以可以在应用程序中使用。利用函数指针,可以调用 EnumWindows 等函数列出系统中打开的窗口,利用 EnumFontFamilies 列出所有的当前字体。利用函数指针还可以访问 Win32 API 中的其它许多函数,早期的 Visual Basic 没有提供对它们的支持。
在 Visual Basic 5.0 中,使用函数指针时仍然存在若干限制。详细信息,请参阅本帮助主题后面的“函数指针的局限与风险”。
有关函数指针的知识
下例可以很好地说明函数指针的用法。首先,看一看 Win32 API 中的 EnumWindows 函数:
Declare Function EnumWindows lib "user32" _
(ByVal lpEnumFunc as Long, _
ByVal lParam as Long ) As Long
EnumWindows 是一个枚举函数,它能够列出系统中每一个打开的窗口的句柄。EnumWindows 的工作方式是重复地调用传递给它的第一个参数(lpEnumFunc,函数指针)。每当 EnumWindows 调用函数,EnumWindows 都传递一个打开窗口的句柄。
在代码中调用 EnumWindows 时,可以将一个自定义函数作为第一个参数传递给它,用来处理一系列的值。例如,可以编写一个函数将所有的值添加到一个列表框中,将 hWnd 值转换为窗口的名字,以及其它任何操作!
为了表明传递的参数是一个自定义函数,可以在函数名称的前面加上 AddressOf 关键字。第二个参数可以是合适的任何值。例如,如果要把 MyProc 作为函数参数,可以按下面的方式调用 EnumWindows:
x = EnumWindows(AddressOf MyProc, 5)
在调用过程时指定的自定义函数被称为回调函数。回调函数(通常简称为“回调”)能够对过程提供的数据执行指定的操作。
回调函数的参数必须具有规定的形式,这是由使用回调函数的 API 决定的。关于需要什么参数,如何调用它们,请参阅 API 文档。
使用 AddressOf 关键字
如果代码要调用 Visual Basic 5.0 的函数指针,则必须将该代码放到标准的 .BAS 模块中,不可以将其放到类模块中,也不能将其附加到窗体上。在使用 AddressOf 关键字声明函数时,必须注意下列事项:
■ AddressOf 只能是参数列表中的第一个参数;该参数可以是自定义的过程、函数或者属性的名字。
■ 写在 AddressOf 后面的过程、函数、属性必须与有关的声明和过程在同一个工程中。
■ AddressOf 只能用于自定义的过程、函数和属性,不能将其用于 Declare 语句声明的外部函数,也不能将其用于类型库中的函数。
■ 在声明的 Sub、Function 或自定义的类型定义中,可以将函数指针传递到 As Any 或 As Long 类型的参数。
注意 可创建用 Visual C++ (或类似的工具)编译的 DLLs 中的回调函数原型。要使用 AddressOf 时,原型必须使用 __stdcall 调用约定。不能将缺省调用约定与 AddressOf 并用
在变量中存储函数指针
在某些情况下,在将函数指针传递到 DLL 之前需要将其存储在一个中间变量中。如果需要将函数指针从一个 Visual Basic 传递到另一个,这种做法是很有用的。例如,在调用 RegisterClass 之类的函数时就需要用结构 (WndClass) 的成员来传递指针。
要将一个函数指针赋予结构中的一个成员,需要编写一个包装函数(wrapper)。例如,下面创建的 FnPtrToLong 就是一个包装函数,使用它可以将函数指针放入任何结构中:
Function FnPtrToLong (ByVal lngFnPtr As Long) As Long
FnPtrToLong = lngFnPtr
End Function
要使用该函数,首先需要声明类型,然后再调用 FnPtrToLong。AddressOf 加上回调函数的名字作为函数的参数。
Dim mt as MyType
mt.MyPtr = FnPtrToLong(AddressOf MyCallBackFunction)
子类派生
利用子类派生技术,可以截取发送到控件或窗体的消息。通过截取这些消息,可以编写自己的代码来改变或者扩展对象的行为。类的派生技术比较复杂,对它的全面讨论将超出本书的范围。下例只能提供该技术的大致轮廓。
重点 当 Visual Basic 处于中断模式时,不允许调用 vtable 方法或 AddressOf 函数。为了保证安全,Visual Basic 仅仅将 0 返回到 AddressOf 函数的调用者。对于子类派生情况,这意味着 WindowProc 将 0 返回到 Windows。Windows 要求它的许多消息返回非 0 值,因此返回的常数 0 将导致 Windows 与 Visual Basic 之间的死锁,从而迫使进程终止。
在下例中,应用程序包括一个简单的窗体,其中只有两个命令按钮。代码的作用是截取发送到窗体的 Windows 消息,并在“立即”窗口中打印出这些消息的值。
代码的第一部分是声明部分,包括 API 函数声明,常数声明和变量声明:
Declare Function CallWindowProc Lib "user32" Alias _
"CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As LongDeclare Function SetWindowLong Lib "user32" Alias _
"SetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long, ByVal dwNewLong As Long) As LongPublic Const GWL_WNDPROC = -4
Global lpPrevWndProc As Long
Global gHW As Long
下一步,使用两个例程“钩入”消息流。第一个过程 (Hook) 调用了 SetWindowLong 函数,它使用了 GWL_WNDPROC 索引来创建窗口类的子类,窗口类是用来创建窗口的。然后它使用 AddressOf 关键字和回调函数 (WindowProc) 来截取消息并在“立即”窗口中打印消息的值。第二个过程 (Unhook) 关闭了子类,重新使原来的 Windows 过程成为回调函数。
Public Sub Hook()
lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _
AddressOf WindowProc)
End SubPublic Sub Unhook()
Dim temp As Long
temp = SetWindowLong(gHW, GWL_WNDPROC, _
lpPrevWndProc)
End SubFunction WindowProc(ByVal hw As Long, ByVal uMsg As _
Long, ByVal wParam As Long, ByVal lParam As Long) As _
Long
Debug.Print "Message: "; hw, uMsg, wParam, lParam
WindowProc = CallWindowProc(lpPrevWndProc, hw, _
uMsg, wParam, lParam)
End Function
最后,窗体的代码设置了 hWnd 的初始值,按钮的代码仅仅调用了上面的两个例程:
Private Sub Form_Load()
gHW = Me.hwnd
End SubPrivate Sub Command1_Click()
Hook
End SubPrivate Sub Command2_Click()
Unhook
End Sub
使用函数指针的局限与风险
使用函数指针是有风险的。每当调用 DLL 的时候,就失去了 Visual Basic 开发环境的稳定性,使用函数指针的危险性就更大了,因为它很容易导致应用程序失败并因此而丢失已完成的工作。在工作的时候必须经常地保存和备份工作成果。下面列出了使用函数指针的一些注意事项:
■ 调试。在中断模式下,如果应用程序引发了回调函数,那么回调函数将被正常执行,但是断点和单步设置将被忽略。如果回调函数产生了异常,则可以捕捉到它并返回当前值。在中断模式下,如果堆栈上有回调函数,那么禁止复位。
■ 形实转换程序。形实转换是 Windows 实现代码重定位的手段。如果在中断模式下删除回调函数,它的形实转换程序将被修改返回 0。该值通常总是正确的,但是也有意外的情况。如果在中断模式下先删除了一个回调函数,然后又再次将其加入,那么有些被调用者可能对新的函数地址一无所知。在 .exe 中不使用形实转换程序,指针被直接传递到入口点。
■ 被传递的函数的签名有误。如果函数的参数个数与调用者期望的不一致,或者在调用某个参数时错误地使用 ByRef 或 ByVal,则应用程序可能会失败。因此,在传递函数时签名一定要正确。
■ 将函数传递给不存在的 Windows 过程。在对某个窗口进行子类派生的时候,需要将一个函数指针作为 Windows 过程 (WindowProc) 传递给 Windows。但是,在 IDE 中运行应用程序时,在调用 WindowProc 时下一层函数可能已经被破坏了。这可能导致一般性保护错误,并使 Visual Basic 开发环境遭到破坏。
■ 不支持“Basic 到 Basic”的函数指针。在 Visual Basic 的内部不能传递指向 Visual Basic 函数的指针。目前,只支持从 Visual Basic 到 DLL 函数的指针。
"
unsigned int len
char threadbuf(1024)
*((long*)threadbuf)=len=> VB
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long) Dim iLen As Integer
Dim sThreadbuf As String * 1024 iLen = &H6261 'ab
CopyMemory ByVal sThreadbuf, ByVal VarPtr(iLen), 2&
Debug.Print sThreadbuf
Dim sThreadbuf As String * 1024 iLen = &H6162
sThreadbuf = "1234" + String(1020, 0)
CopyMemory ByVal sThreadbuf, ByVal VarPtr(CLng(iLen) And &HFFFF&), 4&
Debug.Print sThreadbuf
Debug.Print Asc(Mid(sThreadbuf, 3, 1)), Asc(Mid(sThreadbuf, 4, 1))
前一句:CopyMemory ThreadDataBuf(0), ByVal (VarPtr(Len1)), 4
后一句:CopyMemory ByVal (VarPtr(Len2)), ByVal (VarPtr(ThreadDataBuf(0))), 4
恩, Dim ThreadDataBuff() as Byte?就对了