VB6 da değişken tiplerinin nasıl kopyalandığına ilişkin, bilgilendirme maksatlı döküman...
Değişken tiplerinin memoryde kapladıkları alanlar farklıdır. Bu değişkenlerin memoryde kapladıkları alanı "memory_alani = Len(değişken)" ile hesaplanır. VBA.Len ve VBA.LenB fonksiyonları farklı değer döndürmektedir. Bu nedenle, sadece "Len" ve "LenB" olarak kullanın.
String değişkeni için;
memory_alani = LenB(değişken) kullanılmalıdır. (MultiByte)
Özel tanımlı tipler için sorun yaşayabilirsiniz. Bende tam olarak VB6 da özel tipleri anlayamadım. Bilgisi olan varsa merakımı giderebilir.
Aşağıdaki örnekler, bilgi amaçlıdır. Daha basit yöntemlerle yapmak, tabiki mümkündür. Fakat, ne zaman? nerede? işinize yarayacağı belli olamaz!
Yüksek memory alanına sahip olan byt1(6553500) ve byt2(6553500) byte array değişkenlerini ele alalım. Normalde bu iki arrayi birbirine eşitleyerek değerlerini aktarmak mümkün. Aşağıdaki örnekte iki yöntem arasındaki performans ölçülmektedir.
Option Explicit
Private Declare Sub memcpy _
Lib "kernel32" Alias "RtlMoveMemory" _
(ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long)
Private Sub Command1_Click()
Dim nTime As Currency
Dim byt1() As Byte
Dim byt2() As Byte
ReDim byt1(6553500)
ReDim byt2(6553500)
nTime = Timer * 1000
byt1 = byt2
Debug.Print "Normal:" & (Timer * 1000) - nTime & " ms"
nTime = Timer * 1000
memcpy byt1(0), byt2(0), 6553501
Debug.Print "memcpy:" & (Timer * 1000) - nTime & " ms"
Erase byt1
Erase byt2
End Sub
Bnim bilgisayarımda, bir kaç kez butona bastım ve aşağıdaki sonuçları aldım. Sizde bu değerler farklı olabilir.
Normal:30,0625 ms
memcpy:7,875 ms
Normal:28,75 ms
memcpy:6,5625 ms
Normal:27,4375 ms
memcpy:10,875 ms
Normal:27,0625 ms
memcpy:20,5 ms
Sonuçtan da anlaşıldığı gibi memory kopyalama daha hızlı sonuç veriyor.
Boyutları Farklı Olan İki Arrayi Kopyalamak
Yukarıdaki örnekte tanımlanan byt1() ve byt2() arraylari yeniden boyutlandirilabildikleri için, eşitlemede herhangi bir hata oluşmamıştı. Fakat boyutları belli olan iki arrayi birbirine eşitleyemeyiz. Aynı örneği inceleyecek olursak;
Option Explicit
Private Declare Sub memcpy _
Lib "kernel32" Alias "RtlMoveMemory" _
(ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long)
Private Sub Command1_Click()
Dim nTime As Currency
Dim i As Long
Dim byt1(6553500) As Byte
Dim byt2(6553500) As Byte
'ilk akla gelen kopyalama
'for next ile yapilacak olan kopyalamadir.
nTime = Timer * 1000
For i = 0 To 6553500
byt1(i) = byt2(i)
Next i
Debug.Print "Normal:" & (Timer * 1000) - nTime & " ms"
'memory kopyalama
nTime = Timer * 1000
memcpy byt1(0), byt2(0), 6553501 'toplam alan '0' (sıfır) dahil
Debug.Print "memcpy:" & (Timer * 1000) - nTime & " ms"
End Sub
Benim bilgisayarımda kodu çalıştırdığımda ve butona bir kaç defa bastığımda, aşağıdaki sonuçları aldım.
Normal:449,4375 ms
memcpy:6,25 ms
Normal:388,5625 ms
memcpy:22 ms
Normal:371,9375 ms
memcpy:8,75 ms
Normal:421,5 ms
memcpy:8,3125 ms
Arada büyük bir performans farkı var.
Farklı Değişken Tiplerini Kopyalamak
a) Long değişkenini Byte array değişkenine kopyalamak.
Option Explicit
Private Declare Sub memcpy _
Lib "kernel32" Alias "RtlMoveMemory" _
(ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long)
Private Sub Command1_Click()
Dim byt1() As Byte
Dim nLong As Long
Dim nLongSize As Long
'aşağıdaki değer, bu konuyu anlamamızı
'kolaylaştıracağı için verilmiştir.
nLong = &H11223344 'decimal : 287454020
'Long değişkeni, memoryde 4 byte değerinde alan kaplar
nLongSize = Len(nLong)
'Test
Debug.Print "VBA.Len(nLong) = " & VBA.Len(nLong)
Debug.Print "Len(nLong) = " & Len(nLong)
'array için alan ayir
ReDim byt1(nLongSize - 1) ' "0" sıfır dahil
'memory kopyalama
'memcpy byt1(0), nLong, nLongSize
'bu şekilde de kullanılabilir
'VarPtr fonksiyonu, nLong değerinin, memorydeki
'adres bilgisini döndürür. memcpy fonksiyonuna bu değeri
'ByVal ifadesi ile gönderiyoruz ki, gönderdiğimiz değişken
'içindeki adres bilgisi değişmesin
memcpy byt1(0), ByVal VarPtr(nLong), nLongSize
'çıktı (gözlemin anlaşılır olması için ...
'...hex olarak yazdırıyorum)
Debug.Print "byt1(0) = " & Hex(byt1(0))
Debug.Print "byt1(1) = " & Hex(byt1(1))
Debug.Print "byt1(2) = " & Hex(byt1(2))
Debug.Print "byt1(3) = " & Hex(byt1(3))
'array için ayırdığımız memory alanını siliyoruz
Erase byt1
End Sub
Bendeki çıktı aşağıdaki gibidir.
VBA.Len(nLong) = 9
Len(nLong) = 4
byt1(0) = 44
byt1(1) = 33
byt1(2) = 22
byt1(3) = 11
Not: Yukarıdaki işlemin tersi yapılarak Byte array den Long değişkenine aktarım mümkündür.
String Kopyalama
String kopyalama işlemleri VB6 da biraz can sıkıcıdır. Bu nedenle pek kullanmam.
Aşağıdaki örnekte, herhangi bir String değerini Long'a ve sonra farklı bir String değişkenine kopyalayacağız.
Option Explicit
Private Declare Sub memcpy _
Lib "kernel32" Alias "RtlMoveMemory" _
(ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long)
Private Declare Function malloc _
Lib "kernel32" Alias "GlobalAlloc" _
(ByVal wFlags As Long, _
ByVal dwBytes As Long) As Long
Private Declare Function free _
Lib "kernel32" Alias "GlobalFree" _
(ByVal hMem As Long) As Long
Private Declare Function memsize _
Lib "kernel32" Alias "GlobalSize" _
(ByVal hMem As Long) As Long
Private Sub Command1_Click()
Dim pString As Long
Dim nSrcLen As Long
Dim strSrc As String
Dim strDest As String
'kaynak string değeri
strSrc = "Bu bir denemedir."
nSrcLen = LenB(strSrc)
'memory de yer ayırıyoruz
pString = malloc(0, nSrcLen)
'String den Long a kopyalama
memcpy ByVal pString, ByVal StrPtr(strSrc), nSrcLen
'Hedef için yer ayırıyoruz
strDest = VBA.Space$(Len(strSrc))
'Long dan String e kopyalama
memcpy ByVal StrPtr(strDest), ByVal pString, nSrcLen
'çıktı
Debug.Print "Len(strSrc) : " & Len(strSrc)
Debug.Print "LenB(strSrc) : " & LenB(strSrc)
Debug.Print "Ayrılam Memory Alanı : " & memsize(pString)
Debug.Print "Ayrılam Memory Adresi: " & pString
Debug.Print "Kaynak String : " & strSrc
Debug.Print "Hedef String : " & strDest
'memory alanını serbest bırakıyoruz
free pString
End Sub
Bendeki çıktı aşağıdaki gibidir.
Len(strSrc) : 17
LenB(strSrc) : 34
Ayrılam Memory Alanı : 34
Ayrılam Memory Adresi: 2014240
Kaynak String : Bu bir denemedir.
Hedef String : Bu bir denemedir.
Not: Fonksiyon adlarına takılmayın, "GlobalAlloc", "GlobalFree" ve "GlobalSize" asıl isimlerdir. "malloc" fonksiyonu (C++ ile ilgilenenler varsa) memory de dwBytes kadar yer ayırır. "memsize" fonksiyonu, memory de ayrılan alanı döndürür. "free" fonksiyonu ise bu alanı serbest bırakır.
İyi Çalışmalar
ALINTIDIR!!
Bir kere teşekkür butonuna basmanız yeterli!
Değişken tiplerinin memoryde kapladıkları alanlar farklıdır. Bu değişkenlerin memoryde kapladıkları alanı "memory_alani = Len(değişken)" ile hesaplanır. VBA.Len ve VBA.LenB fonksiyonları farklı değer döndürmektedir. Bu nedenle, sadece "Len" ve "LenB" olarak kullanın.
String değişkeni için;
memory_alani = LenB(değişken) kullanılmalıdır. (MultiByte)
Özel tanımlı tipler için sorun yaşayabilirsiniz. Bende tam olarak VB6 da özel tipleri anlayamadım. Bilgisi olan varsa merakımı giderebilir.
Aşağıdaki örnekler, bilgi amaçlıdır. Daha basit yöntemlerle yapmak, tabiki mümkündür. Fakat, ne zaman? nerede? işinize yarayacağı belli olamaz!
Yüksek memory alanına sahip olan byt1(6553500) ve byt2(6553500) byte array değişkenlerini ele alalım. Normalde bu iki arrayi birbirine eşitleyerek değerlerini aktarmak mümkün. Aşağıdaki örnekte iki yöntem arasındaki performans ölçülmektedir.
Option Explicit
Private Declare Sub memcpy _
Lib "kernel32" Alias "RtlMoveMemory" _
(ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long)
Private Sub Command1_Click()
Dim nTime As Currency
Dim byt1() As Byte
Dim byt2() As Byte
ReDim byt1(6553500)
ReDim byt2(6553500)
nTime = Timer * 1000
byt1 = byt2
Debug.Print "Normal:" & (Timer * 1000) - nTime & " ms"
nTime = Timer * 1000
memcpy byt1(0), byt2(0), 6553501
Debug.Print "memcpy:" & (Timer * 1000) - nTime & " ms"
Erase byt1
Erase byt2
End Sub
Bnim bilgisayarımda, bir kaç kez butona bastım ve aşağıdaki sonuçları aldım. Sizde bu değerler farklı olabilir.
Normal:30,0625 ms
memcpy:7,875 ms
Normal:28,75 ms
memcpy:6,5625 ms
Normal:27,4375 ms
memcpy:10,875 ms
Normal:27,0625 ms
memcpy:20,5 ms
Sonuçtan da anlaşıldığı gibi memory kopyalama daha hızlı sonuç veriyor.
Boyutları Farklı Olan İki Arrayi Kopyalamak
Yukarıdaki örnekte tanımlanan byt1() ve byt2() arraylari yeniden boyutlandirilabildikleri için, eşitlemede herhangi bir hata oluşmamıştı. Fakat boyutları belli olan iki arrayi birbirine eşitleyemeyiz. Aynı örneği inceleyecek olursak;
Option Explicit
Private Declare Sub memcpy _
Lib "kernel32" Alias "RtlMoveMemory" _
(ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long)
Private Sub Command1_Click()
Dim nTime As Currency
Dim i As Long
Dim byt1(6553500) As Byte
Dim byt2(6553500) As Byte
'ilk akla gelen kopyalama
'for next ile yapilacak olan kopyalamadir.
nTime = Timer * 1000
For i = 0 To 6553500
byt1(i) = byt2(i)
Next i
Debug.Print "Normal:" & (Timer * 1000) - nTime & " ms"
'memory kopyalama
nTime = Timer * 1000
memcpy byt1(0), byt2(0), 6553501 'toplam alan '0' (sıfır) dahil
Debug.Print "memcpy:" & (Timer * 1000) - nTime & " ms"
End Sub
Benim bilgisayarımda kodu çalıştırdığımda ve butona bir kaç defa bastığımda, aşağıdaki sonuçları aldım.
Normal:449,4375 ms
memcpy:6,25 ms
Normal:388,5625 ms
memcpy:22 ms
Normal:371,9375 ms
memcpy:8,75 ms
Normal:421,5 ms
memcpy:8,3125 ms
Arada büyük bir performans farkı var.
Farklı Değişken Tiplerini Kopyalamak
a) Long değişkenini Byte array değişkenine kopyalamak.
Option Explicit
Private Declare Sub memcpy _
Lib "kernel32" Alias "RtlMoveMemory" _
(ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long)
Private Sub Command1_Click()
Dim byt1() As Byte
Dim nLong As Long
Dim nLongSize As Long
'aşağıdaki değer, bu konuyu anlamamızı
'kolaylaştıracağı için verilmiştir.
nLong = &H11223344 'decimal : 287454020
'Long değişkeni, memoryde 4 byte değerinde alan kaplar
nLongSize = Len(nLong)
'Test
Debug.Print "VBA.Len(nLong) = " & VBA.Len(nLong)
Debug.Print "Len(nLong) = " & Len(nLong)
'array için alan ayir
ReDim byt1(nLongSize - 1) ' "0" sıfır dahil
'memory kopyalama
'memcpy byt1(0), nLong, nLongSize
'bu şekilde de kullanılabilir
'VarPtr fonksiyonu, nLong değerinin, memorydeki
'adres bilgisini döndürür. memcpy fonksiyonuna bu değeri
'ByVal ifadesi ile gönderiyoruz ki, gönderdiğimiz değişken
'içindeki adres bilgisi değişmesin
memcpy byt1(0), ByVal VarPtr(nLong), nLongSize
'çıktı (gözlemin anlaşılır olması için ...
'...hex olarak yazdırıyorum)
Debug.Print "byt1(0) = " & Hex(byt1(0))
Debug.Print "byt1(1) = " & Hex(byt1(1))
Debug.Print "byt1(2) = " & Hex(byt1(2))
Debug.Print "byt1(3) = " & Hex(byt1(3))
'array için ayırdığımız memory alanını siliyoruz
Erase byt1
End Sub
Bendeki çıktı aşağıdaki gibidir.
VBA.Len(nLong) = 9
Len(nLong) = 4
byt1(0) = 44
byt1(1) = 33
byt1(2) = 22
byt1(3) = 11
Not: Yukarıdaki işlemin tersi yapılarak Byte array den Long değişkenine aktarım mümkündür.
String Kopyalama
String kopyalama işlemleri VB6 da biraz can sıkıcıdır. Bu nedenle pek kullanmam.
Aşağıdaki örnekte, herhangi bir String değerini Long'a ve sonra farklı bir String değişkenine kopyalayacağız.
Option Explicit
Private Declare Sub memcpy _
Lib "kernel32" Alias "RtlMoveMemory" _
(ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long)
Private Declare Function malloc _
Lib "kernel32" Alias "GlobalAlloc" _
(ByVal wFlags As Long, _
ByVal dwBytes As Long) As Long
Private Declare Function free _
Lib "kernel32" Alias "GlobalFree" _
(ByVal hMem As Long) As Long
Private Declare Function memsize _
Lib "kernel32" Alias "GlobalSize" _
(ByVal hMem As Long) As Long
Private Sub Command1_Click()
Dim pString As Long
Dim nSrcLen As Long
Dim strSrc As String
Dim strDest As String
'kaynak string değeri
strSrc = "Bu bir denemedir."
nSrcLen = LenB(strSrc)
'memory de yer ayırıyoruz
pString = malloc(0, nSrcLen)
'String den Long a kopyalama
memcpy ByVal pString, ByVal StrPtr(strSrc), nSrcLen
'Hedef için yer ayırıyoruz
strDest = VBA.Space$(Len(strSrc))
'Long dan String e kopyalama
memcpy ByVal StrPtr(strDest), ByVal pString, nSrcLen
'çıktı
Debug.Print "Len(strSrc) : " & Len(strSrc)
Debug.Print "LenB(strSrc) : " & LenB(strSrc)
Debug.Print "Ayrılam Memory Alanı : " & memsize(pString)
Debug.Print "Ayrılam Memory Adresi: " & pString
Debug.Print "Kaynak String : " & strSrc
Debug.Print "Hedef String : " & strDest
'memory alanını serbest bırakıyoruz
free pString
End Sub
Bendeki çıktı aşağıdaki gibidir.
Len(strSrc) : 17
LenB(strSrc) : 34
Ayrılam Memory Alanı : 34
Ayrılam Memory Adresi: 2014240
Kaynak String : Bu bir denemedir.
Hedef String : Bu bir denemedir.
Not: Fonksiyon adlarına takılmayın, "GlobalAlloc", "GlobalFree" ve "GlobalSize" asıl isimlerdir. "malloc" fonksiyonu (C++ ile ilgilenenler varsa) memory de dwBytes kadar yer ayırır. "memsize" fonksiyonu, memory de ayrılan alanı döndürür. "free" fonksiyonu ise bu alanı serbest bırakır.
İyi Çalışmalar
ALINTIDIR!!
Bir kere teşekkür butonuna basmanız yeterli!

