VB 中CopyMemory的用法
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private Sub Form_Load()
Dim A(15) As Byte, B(15) As Byte
B(0) = &HAF
B(1) = &H82
B(2) = &H25
B(3) = &H74
CopyMemory A(0), B(0), 4 '目标,源,大小-字节
Debug.Print Hex(A(0)), Hex(A(1)), Hex(A(2)), Hex(A(3)), Hex(A(4))
End Sub
Private Sub Command1_Click()
Dim B(15) As Byte
B(0) = &HAF
B(1) = &H82
B(2) = &H25
B(3) = &H74
iLength = 0
CopyMemory B(4), iLength, 4
Debug.Print B(0), B(1), B(2), B(3), Hex(B(4)), Hex(B(5)), Hex(B(6)), Hex(B(7))
dwOrdinal = 0
CopyMemory B(8), dwOrdinal, 4
Debug.Print B(0), B(1), B(2), B(3), Hex(B(4)), Hex(B(5)), Hex(B(6)), Hex(B(7)), Hex(B(8)), Hex(B(9)), Hex(B(10)), Hex(B(11))
Dim dwCheckSum As Long
dwCheckSum = 0
CopyMemory B(12), dwCheckSum, 4
End Sub
这样应该容易理解了吧~你源内存地址写的是0 该地址上的第一个字节就是2 所以以你上面的代码来看B数组中的4,8,12元素都是2
VB6怎么使用copymemory直接复制数组?
CopyMemory()函数功能描述:将一块内存的数据从一个位置复制到另一个位置。函数原型VOID CopyMemory(PVOID Destination,CONST VOID *Source,SIZE_T Length);参数Destination 要复制内存块的目的地址。Source 要复制内存块的源地址。Length 指定要复制内存块的大小,单位为字节返回值 该函数为VOID型,没有返回值。备注 如果目的块与源块有交叠,结果是不可预料的,使用MoveMemory可以解决这个问题。注意一点CopyMemory和MoveMemory不过是RtlMoveMemory的一个别名。编程语言特点1.可视化Visual basic是可视化的程序设计语言,开发人员只需要按照设计要求对屏幕进行布局,用集成开发环境来直接拖和画出各个菜单、按钮、滚动条、窗口等不同类型的对象。2.面向对象在visual basic 中,窗体及控件都称为对象,有这些对象构成了用户界面,visual basic是面向对象的程序设计语言,它是将代码和数据结合在每个对象中,用户只需要了解每个对象能完成什么任务,不必知道对象是如何工作的,而程序设计人员只要编写实现程序功能的那部分代码,这样大大提高了程序设计的效率,但是visual basic里面没有多态等面向对象的特性,所以有人称visual basic是准面向对象程序设计语言。3.事件驱动Visual basic通过事件来执行对象的操作,一个对象可能会产生多个事件,每个事件都可以通过一段程序来响应,而各个事件之间却不一定有联系,这样的应用程序代码较短,使程序既易于编写又易于维护。4.沿用结构化的程序设计的思想Visual basic具有丰富的数据类型,众多的函数,并采 用了结构化的程序 设 计方法,简单易学。5.易学易用的集成开发环境Visual basic提供了易学易用的集成开发环境,在该开发环境中,用户可设计用户界面,编写代码,调试程序,直至把应用程序编译成可执行文件使其直接在windows环境下运行6.支持多种数据库的访问采用了对象的链接与嵌入(OLE,Object linking and embedding)技术可以很方便的开发出集声音、图像、动画、子处理、web等对象于一体的应用程序。最新版本Visual basic 6.0(简称VB6)所提供的开发环境与Windows 9x,Windows NT4.0或Windows2000具有完全一致的界面,使用更方便,其代码效率已达到Visual C++的水平.在面向对象程序设计方面,6.0版的VB全面支持面向对象的程序设计,包括数据抽象,封装,对象与属性,类与成员,继承和多态等。Visual Basic6.0包括三种版本即学习版,专业版和企业版,这些版本是在相同的基础上建立起来的,因此大多数应用程序可以在三种版本中通用。Visual Basic 6.0 是用来创建高性能的企业应用程序及基于 Web的应用程序的最有效工具。Visual Basic 6.0 使开发者得以创建驻留在客户或服务器上或运行在分布式n-层环境里的强壮应用程序。Visual Basic 6.0 这个快速应用开发工具既可以作为一个单独的产品也可以作为 Visual Studio 6.0 套件的一个组成部分。
Excel 求助CopyMemory的使用方法
这个函数的声明大体有两种: A: Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (Destination As Any, Source As Any, ByVal Length As Long) B: Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (ByVal Destination As Long, ByVal Source As Long,ByVal Length As Long) 虽然使用B有其理由,但为避免混乱,这里使用A的声明方式,初学者只需把A声明拷贝到模块开头就可以使用Copymemory函数了,其他不必深究。 2. 其实这个函数本身非常简单: Copymemory 参数2, 参数1, a 记住:参数1 ,参数2 都是内存一块区域开头的地址,这个函数的意思是:把从参数1开头的地址,往后数a长度这么大的区域,复制到参数2开头的区域中。 3. 见下图:这个函数无非是把0015F7C0(参数1)开头的区域,红框1处的内容,复制到以0015F7C4(参数2)开头的区域,即红框2处, 这里第3个参数为4,意即复制四个字节的内容。
急求十六进制转浮点数C程序!!!
楼主你好.
楼上的解决方式是很对的。
这个问题的解决需要这样的一个思想:将需要转换的数值的地址取出,赋值给一个“想要转换成的”数据类型的地址(也就是指针),然后取需要的内存单元中的内容就可以了
例如对一个赋了值的十六进制的变量n,需要转换成float型的,就是先取其地址&n,赋给一个float型的指针,也就是(float*)&n,然后取指针的内容*(float)&n就可以了。
需要注意的是,这个方法只适用于所需转换的数据在内存中所占大小与需要转换成的数据类型在内存中所占大小相同的情况(如VC6中,float型数据占4个字节,而每个字节是两位十六进制数,4个字节也就是八位十六进制数,正好等于你需要转换的十六进制数的位数,故此方法可行)
希望我的回答能帮到你~!
以下附上参考程序段:
#include
float Hex_To_Decimal(unsigned char *Byte,int num)//十六进制到浮点数
{
// char cByte[4];//方法一
// for (int i=0;i<num;i++)
// {
// cByte[i] = Byte[i];
// }
//
// float pfValue=*(float*)&cByte;
//return pfValue;
return *((float*)Byte);//方法二
}
long FloatTohex(float HEX)//浮点数到十六进制转换1
{
return *( long *)&HEX;
}
void FloatToByte(float floatNum,unsigned char* byteArry)////浮点数到十六进制转换2
{
char* pchar=(char*)&floatNum;
for(int i=0;i<sizeof(float);i++)
{
*byteArry=*pchar;
pchar++;
byteArry++;
}
}
void main()
{
unsigned char floatToHex[4];
unsigned char hexbyte[4]={0xd0,0x0f,0x49,0x40};//传输数据为3d cc cc cd,0xcd,0xCC,0xCC,0x3D,40490fd0
float Hdecimal=0.0;
float flh=0.4;
Hdecimal=Hex_To_Decimal(hexbyte,sizeof(hexbyte));//十六进制转换为浮点数
printf("\n 浮点数为:\n %f\n",Hdecimal);
long hX=FloatTohex(Hdecimal);//浮点数转换为十六进制一
printf("\n正序十六进制值:\n %f=%X \n",Hdecimal,hX);//正序显示
FloatToByte(Hdecimal,floatToHex);//浮点数转为十六进制二
printf("\n倒序十六进制:\n%f=%x %x %x %x\n",Hdecimal,floatToHex[0],floatToHex[1],floatToHex[2],floatToHex[3] );//倒序显示
}
VB中CopyMemory用法
两者效果并不一样。在理解之前,你需要知道VB对于字符串的处理方式。string1变量,本质上是一个指针,指向实际的字符串开头位置,这个位置再往前的4个字节是一个long,表示字符串的长度。
第一种,ByVal String2,实际效果是把string2的内容直接传递给copymemory(严格的说不是,VB有别的小动作),CopyMemory 的执行效果就是把string1指向的字符串复制5个字符到string2指向的字符串,这种写法在VB里是最正确的。
第二种,如果用第二种copymemory的声明,效果就是CopyMemory byval VarPtr(String2),byval VarPtr(String1), 4。这样表面上能复制,实际情况是,VarPtr(String2)获得string2自身的地址而不是string2保存的内容也就是那个指针,然后传给函数,也就是把string1的值强制复制给了string2,执行完之后,string1、2指向同一个位置(因为他们的值一样)。只要别改变string1的字符串内容,以后string2一直等于string1 。但如果你写了这句 string1=“asdf”,每次给字符串赋值时VB都要重新分配内存,这样,string1是个正常的变量,但string2还是指向老地方(那里已经不属于string1了),所以Print string2显示的一般是乱码。
另外,每次运行这类内存相关的函数前要保存,一个粗心就导致VB崩了,重打字麻烦O(∩_∩)O~
DELPHI CopyMemory问题
调用CopyMemory之前,如果已经为指针分配了内存,就不需要调用GetMem。举个例子:
var
s1, s2: string;
begin
s1 := '123';
s2 := 'abc';
CopyMemory(@s2[1], @s1[1], 3);
{s2 = '123'}
end;
又如:
var
b: Byte;
i: Integer;
begin
b := 0;
i := 511;
CopyMemory(@i, @b, 1);
{i的低8位被置0,i = 256}
end;
VC,用CreateThread创建的线程中使用CopyMemory会导致内存泄漏吗?CopyMemory到底是C标准库的还是VC的?
关于CreateThread的这个问题这个你不用顾虑的,摘抄核心编程内容如下:
也许你想知道,如果调用C r e a t e T h r e a d,而不是调用C / C + +运行期库的_ b e g i n t h r e a d e x来创建新线程,将会发生什么情况。当一个线程调用要求t i d d a t a结构的C / C + +运行期库函数时,将会发生下面的一些情况(大多数C / C + +运行期库函数都是线程安全函数,不需要该结构)。首先, C / C + +运行期库函数试图(通过调用T l s G e t Va l u e )获取线程的数据块的地址。如果返回N U L L作为t i d d a t a块的地址,调用线程就不拥有与该地址相关的t i d d a t a块。这时,C / C + +运行期库函数就在现场为调用线程分配一个t i d d a t a块,并对它进行初始化。然后该t i d d a t a块(通过T l s S e t Va l u e)与线程相关联。此时,只要线程在运行,该t i d d a t a将与线程待在一起。这时,C / C + +运行期库函数就可以使用线程的t i d d a t a块,而且将来被调用的所有C / C + +运行期函数也能使用t i d d a t a块。
当然,这看来有些奇怪,因为线程运行时几乎没有任何障碍。不过,实际上还是存在一些问题。首先,如果线程使用C / C + +运行期库的s i g n a l函数,那么整个进程就会终止运行,因为结构化异常处理帧尚未准备好。第二,如果不是调用_ e n d t h r e a d e x来终止线程的运行,那么数据块就不会被撤消,内存泄漏就会出现(那么谁还为使用C r e a t e T h r e a d函数创建的线程来调用_ e n d t h r e a d e x呢?)。
注意如果程序模块链接到多线程D L L版本的C / C + +运行期库,那么当线程终止运行并释放t i d d a t a块(如果已经分配了t i d d a t a块的话)时,该运行期库会收到一个D L L _ T H R E A D _ D E TA C H通知。尽管!!!!这可以防止t i d d a t a块的泄漏!!!!,但是强烈建议使用_ b d g i n t h r e a d e x而不是使用C r e a t e t h r e a d来创建线程。
另外:
CopyMemory是API,可以随便调用的。memcpy才是C库里面的。
请教copymemory问题
在 VB 中处于安全考虑,不能直接访问内存,
但你可以使用 CopyMemory(RtlMoveMemory) 的 API 来复制指定区域的内存,
其具体声明如下:
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
其中,
Destination 是指向复制目标的指针,可以直接指定为某个变量或是数组(如果是数组应使用 myArray(0) 或是 myArray(n) 来指定覆盖的起点,不能直接使用 myArray),或是使用 ByVal 关键字加内存地址
Source 是复制源的指针,用法与上面一样
Length 是复制的长度,以字节为单位。
然后是 VB 6 中没有公开的三个函数:VarPtr,StrPtr,ObjPtr
它们分别返回变量、字符串、对象的指针(就是内存地址)
因此,在执行:
copymemory b(0),byval "1234",4
时,VB 会先在内存中划出一块儿区域,
用于保存值为 "1234" 的字符串,
然后把这个字符串的指针传给 CopyMemory,
CopyMemory 把内存中刚才保存字符串数据的地址处的数据复制到数组 b 中,
从 b(0) 开始覆盖,覆盖 4 个字节
VB 6 在调用 API 时,字符串一般是按值(ByVal)传递,
在传递时以 ANSI 编码。
也就是说,上面那句代码等价于(为了安全性,我个人推荐下面这种做法):
Erase b
b = StrConv("1234", vbFromUnicode)
而
copymemory byval varptr(a(0)),1234,4
其实就是
CopyMemory a(0),1234,4
在执行时,
VB 会先在内存中划出 2 个字节(1234 等价于 1234% 或是 CInt(1234))
用于保存值为 1234 的 Integer,
然后在执行 CopyMemory 时,
把内存中刚才保存有 1234 处的数据复制到数组 b 中,
从 a(0) 开始覆盖,覆盖 4 个字节。
问题是,
你把指针给人家时,只在对应的位置划了 2 个字节,
你却要人家从你给的位置读 4 个字节……
由于后两个字节没有被分配,
因此可能会返回一个任意值,
不排除崩溃的可能,
而且还是你的程序带着开发环境 IDE 一块儿崩溃。
估计你本来应该这么写(我觉得 byval varptr(...) 累赘了):
CopyMemory a(0),1234&,4
这样,划出来的就是 4 个字节(Long)了。
可是,如果是这样,那你还不如用:
a(0) = 1234
又方便,又安全……
还有,
CopyMemory 只负责复制,不负责分配内存。
因此你在把 a、b 数组当成复制覆盖的目标之前,
至少需要分配一下内存吧(若你是在问题中省略了就算了……)
例如:
ReDim a(0) '4 x 1 = 4 字节
ReDim b(3) '1 x 4 = 4 字节
但如果你准备使用
b = StrConv("1234", vbFromUnicode)
这样的代码,
则 b 一定要是空的,如果不是,则需要使用 Erase 清空。