string的问题
vb吧
全部回复
仅看楼主
level 2
一个结构体
Private Type table
sz as string
total As Long
End Type
然后
Dim t(10) As table, ct(10) As table
Dim p As LongPtr
Dim sz() As Byte
t(0).sz = "a001"
t(0).total = 200
t(1).sz = "a002"
t(1).total = 300
p = VarPtr(ct(0))
CopyMemory ByVal p, t(0), LenB(t(0)) * 10
Debug.Print StrConv(ct(0).sz, vbUnicode)
Debug.Print StrConv(ct(1).sz, vbUnicode)
最后虽然ct(0)能输出去,但结尾一堆乱码,ct(1)也输不出来
为何?
2021年03月06日 17点03分 1
level 5
vb生成个dll,什么类型都谁便➕,
2021年03月06日 19点03分 2
level 5
数组类型复杂的不好使,
2021年03月06日 19点03分 3
level 11
还没有找到问题先说一下:
你的CopyMemory默认到底是传指针还是传引用?如果是传指针,你的这个t(0)应该不能这么用,换言之你这应该是传引用,但如此的话,你的结果最终是反馈到从变量p地址开始的内存空间,换言之不能影响ct数组
2021年03月07日 00点03分 4
上午看漏了一个byval......
2021年03月07日 09点03分
level 13
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Type table
sz As String
total As Long
End Type
Private Sub Form_Load()
Dim t(10) As table, ct(10) As table
Dim p As Long, p2 As Long
t(0).sz = "a001"
t(0).total = 200
t(1).sz = "a002"
t(1).total = 300
p = VarPtr(ct(0))
p2 = VarPtr(t(0))
CopyMemory ByVal p, ByVal p2, LenB(t(0)) * 11 '还有这里应当是11,不是10,VB的数组没有指定的情况下是从0开始到10结束,是11个元素(我想楼主要应该的是一整个结构数组复制到另一个结构数组)
Debug.Print ct(0).sz
Debug.Print ct(1).sz
End Sub
2021年03月07日 14点03分 7
谢谢,我把sz定义为byte就可以,感觉真奇怪
2021年03月07日 17点03分
level 11
7楼楼中楼:
因为String实际上是个BSTR,其在面向用户时储存的为一个指向实际数据存储地址的一个指针,为4字节(前面大佬也说过)
我并不知道直接传结构数组的一个成员时,其引用到底传的是什么,但我昨天测试了几次,尝试CopyMemory直接传ct(0)和t(0)的引用直接报错,只有传指针时才成功运行,所以我就很奇怪你是怎么运行成功的,但因为某些原因,后面就没测试了,也就没提问了
对了Len函数传入一个结构体时返回的是结构体的大小,LenB也一样,就算当中存在字符串变量,也不是返回的其字符串变量的长度
2021年03月07日 23点03分 8
现在更神奇了,我本是在vba里面运行的代码,现在不知道为什么一用copy memory这个函数整个excel直接崩了
2021年03月08日 13点03分
我觉得用lenb是因为有汉字的时候传2个字符吧
2021年03月08日 13点03分
@( •̀_•́ ) CopyMemory见大佬11楼描述,LenB结合本楼和大佬9楼解释,另0-10有11个这个也注意下
2021年03月08日 13点03分
level 13
'测试了下,分析如下
Option Explicit
'Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Type table
sz As String
total As Long
End Type
Private Sub Form_Load()
Dim t(10) As table, ct(10) As table, newt(10) As table
Dim p As Long, p2 As Long
t(0).sz = "a001"
t(0).total = 200
t(1).sz = "a002"
t(1).total = 300
p = VarPtr(ct(0))
'p2 = VarPtr(t(0))
'CopyMemory ByVal p, ByVal p2, LenB(t(0)) * 11 '还有这里应当是11,不是10,VB的数组没有指定的情况下是从0开始到10结束,是11个元素(我想楼主要应该的是一整个结构数组复制到另一个结构数组)
'
'Debug.Print StrPtr(t(0).sz) '用上面的那种方法Copy,实际上将t(0).sz的指针复制到ct(0).sz中,所以t(0).sz和ct(0).sz都指同一个字符串(某种情况下这种方法还是有优势的)
'Debug.Print StrPtr(ct(0).sz) '连StrPtr得到的都是一样地址
'
't(0).sz = "pp" '当重新赋值字符串时,指针会改变,这里再StrPtr(t(0).sz)地址就变动了
'
'Debug.Print ct(0).sz
'Debug.Print ct(1).sz
'
'
'
'Debug.Print StrPtr(newt(0).sz) '返回0,得到结构的sz是个空字串,相当于C++的NULL(空指针)
'Debug.Print newt(0).sz = vbNullString '返回True
'Debug.Print LenB(newt(0)) '得到8字节,说明结构里sz as string是个字符串指针,占4字节
CopyMemory ByVal p, t(0), LenB(t(0)) * 11 'Declare声明的CopyMemory执行就会崩溃(如果写到TLB后调用,则正常)
Debug.Print ct(0).sz
Debug.Print ct(1).sz
End Sub
2021年03月08日 11点03分 11
@悲观集合 如果用你原先的代码,则可以将CopyMemory写入tlb后调用
2021年03月08日 11点03分
直接传t(0)的话要将其API函数写入tlb吗?难怪测试几次都是出错[笑尿]
2021年03月08日 12点03分
2021年03月08日 12点03分
@余思培 因为Declare声明会先调用msvbvm60.dll的DLLFunctionCall,再由DLLFunctionCall调用CopyMemory,而tlb后调用则直接调用CopyMemory,中间没有了对DLLFunctionCall的调用,所以问题应该在这,大概是DLLFunctionCall不支持
2021年03月08日 12点03分
1