VisualBasic深度下潛之海蛇纏繞
“海蛇”有人在驚呼。
只見在海底深處游來一條黑色的長長的海蛇,幾乎所有的人都在發呆。但是海蛇說了一句讓我們膽寒的話“我就是有名的VB字符串,如果你們繼續下潛的話,就得想通過我”。
我習慣性的觀察著它,因為我知道要打敗一個對手,就必須深入的了解對手。
因此我寫了一段小CODE來了解它。
這個代碼運行得很好,完全符合我的想像,在立即窗口中顯示了12,24,
Good,于是我準備在窗口中用TextOut把它打印出來,至于為什么我一定要這個函數而不用其它的,你管得著么?所以我寫下了于下代碼
結果我發現不對?看來是字符串長度不對,想起來了,在VB中字符串是BSTR型的,那么應該用L2作長度,對不對呢,試試就知道了。
天呀,在字符串后出現了天書,難道是上帝在暗示我什么時候給我一個美女?
不過我想上帝沒有這么快就會答應我,因此一定是我的代碼有問題。
當我正在沉思的時候,所有的人都在觀注著我。沒辦法,太帥了。
所以我又迅速寫下了以下的代碼
當我快速地按下F5后,天空中便有了回響,“Give me a 美女”這句話已得到了正確的響應。
這時候我看著這條海蛇,滿有信心地向它游去,但是它卻很詭秘的一笑。
你見過蛇的笑容么,它也很緩緩的游過來了。
“如果你們打算就這樣通過我的話,也想得太容易了”這句話為什么這么熟悉呢。是不是在黃金十二宮里的什么人說的吧,
“給你們一個小考驗,你們知道vbNullString 和 “” 有什么區別么?”
“別以為你是海蛇就了不起,你這問題也太簡單了吧”我身邊一個長得不是很難看的小伙子,人送外號(天下第七帥),“你以為我沒讀過海洋生物指南呀(對象瀏覽器)
Const vbNullString = ""
VBA.Constants 的成員
當調用一個外部過程,需要一個非零值的字符串時,所使用的常數
“那你的意思是說是一樣的了,那么vbNullChar呢?”海蛇不懷好意地看著天下第七帥。
“那當然是一樣的了,你看VB的說明么”天下第七帥沖口而出,不過他又覺得好象有些不對。但是VB的對象瀏覽器上的確寫著
VBA.Constants 的成員
那么下面這段代碼代表什么呢?
海蛇給出了它的代碼
天下第七帥按下F5后,他很驚訝海蛇代碼的運行結果
0 1899284 1434596
0 2 0
那么就是說VB的說明和海蛇之間一定有人錯了。而且,對于采用S1兩個值都是零,指針指向零,長度為零,它不是一個普通意義上的零值呀。
天下第七帥于是轉過頭來看著我。
“小子,出風頭吧,來吧,我先給你們看點東西”
“你們想要打敗海蛇,就一定要了解海蛇的結構”
VB的字符串是一個標準的BSTR字符串,比如說”Hello”這個字符串它的結構是這樣的
可以看到前面四個字節代表 字符串實際長度所占字節數,它是一個Long值。
而最后兩個字節是代表零值的結尾字符。
而中間的十個字節正好是字符串的內容。
如果我們用s1=”Hello”,那么s1是指向什么地方呢。
“最初我以為s1是指向第一個字節,但是當我用自編的VB內存觀測工具來看strptr(s1)后面所跟的字節值時發現,s1是指向第五個字節,也就是我們字符串真正開始的地方。”
“大家都了解了海蛇的結構了,那么它剛才提出的三種情況為什么會有不同呢?”我向還在發呆的下潛者。
“是呀,為什么?”
好了,拿出你們的OleView,在File-> View TypeLib中打開VB6.DLL,你是不是看到了一個很奇妙的天地,別發呆,找到以下部分
打開他們你便會看到VB內部真正的定義了。
看到了沒有,vbNullString指向一個空字串,但這個空字串是零址的。而vbNullChar則是一個零字符(相當于C中字符串中最后一個字符)。那么我們來看海蛇的代碼運行時發生了什么
VB看到這句時,它很清楚把S1的值變成了零
VB看到這句時,它做了幾個動作,它用SysAllocStringLen在堆中分配了一個BSTR字符串,然后將’’復制到這個字符串里。
這里VB做了很多工作,首先,VB在編譯時,把""當成了一個常量,它必須為這個空字符串內部申請一個變量。當EXE文件加載后,也得把它設定一個地址,雖然它什么都不代表
是一個 00 00 00 00 00 00 這樣的字符串,它需要6個字節(四個頭字節和2個尾字節)
然后當看到這句時再把第五個字節的地址值傳給s3
所以,雖然你只是信手寫了一個"",結果VB多作了很多工作。6個字節雖然不多,但是在一個大工程里,大家都到處寫“”,那么也是很可觀的一筆開銷。所以下次你絕對不要再用"",而一定要用vbNullString
“你說,是么,海蛇”,我輕蔑地看著它。
海蛇看到大家都恍然大悟的樣子,再此發出了它的笑聲(海蛇會笑么?)
“了解我,并不是真正的掌控我,很多C的潛水員會對VB不屑一顧,你們知道是為什么?”
“慢,VB的字符串操作太慢了”很多潛水者都回搶著回答這個問題。
“呵呵,是的,”海蛇放聲大笑,慢慢地游向深海“I will Back!”
留下我們這群潛水的人,大家在思索,我們真正了解海蛇了么,因為VB海洋傳說中海蛇是相當可怕的,它會這么輕易地走開么,而且,它所說的 I will Back又是指什么?
但是我們會繼續下潛…….
“看,珊瑚礁”有人在驚呼!
只見在海底深處游來一條黑色的長長的海蛇,幾乎所有的人都在發呆。但是海蛇說了一句讓我們膽寒的話“我就是有名的VB字符串,如果你們繼續下潛的話,就得想通過我”。
我習慣性的觀察著它,因為我知道要打敗一個對手,就必須深入的了解對手。
因此我寫了一段小CODE來了解它。
| Dim str As String str = "Give me a 美女" Dim L1 As Long Dim L2 As Long L1 = Len(str) L2 = LenB(str) Debug.Print L1, L2 |
這個代碼運行得很好,完全符合我的想像,在立即窗口中顯示了12,24,
Good,于是我準備在窗口中用TextOut把它打印出來,至于為什么我一定要這個函數而不用其它的,你管得著么?所以我寫下了于下代碼
| Dim str As String str = "Give me a 美女" Dim L1 As Long Dim L2 As Long L1 = Len(str) L2 = LenB(str) Debug.Print L1, L2 TextOut Me.hDC, 100, 100, str, L1 |
結果我發現不對?看來是字符串長度不對,想起來了,在VB中字符串是BSTR型的,那么應該用L2作長度,對不對呢,試試就知道了。
天呀,在字符串后出現了天書,難道是上帝在暗示我什么時候給我一個美女?
不過我想上帝沒有這么快就會答應我,因此一定是我的代碼有問題。
當我正在沉思的時候,所有的人都在觀注著我。沒辦法,太帥了。
所以我又迅速寫下了以下的代碼
| Private Declare Function LenANSI Lib "kernel32" Alias "lstrlenA" (ByVal string1 As String) As Long …… Dim str As String str = "Give me a 美女" Dim TrueLen As Long TrueLen = LenANSI(str) TextOut Me.hDC, 100, 100, str, TrueLen |
當我快速地按下F5后,天空中便有了回響,“Give me a 美女”這句話已得到了正確的響應。
這時候我看著這條海蛇,滿有信心地向它游去,但是它卻很詭秘的一笑。
你見過蛇的笑容么,它也很緩緩的游過來了。
“如果你們打算就這樣通過我的話,也想得太容易了”這句話為什么這么熟悉呢。是不是在黃金十二宮里的什么人說的吧,
“給你們一個小考驗,你們知道vbNullString 和 “” 有什么區別么?”
“別以為你是海蛇就了不起,你這問題也太簡單了吧”我身邊一個長得不是很難看的小伙子,人送外號(天下第七帥),“你以為我沒讀過海洋生物指南呀(對象瀏覽器)
Const vbNullString = ""
VBA.Constants 的成員
當調用一個外部過程,需要一個非零值的字符串時,所使用的常數
“那你的意思是說是一樣的了,那么vbNullChar呢?”海蛇不懷好意地看著天下第七帥。
“那當然是一樣的了,你看VB的說明么”天下第七帥沖口而出,不過他又覺得好象有些不對。但是VB的對象瀏覽器上的確寫著
| Const vbNullChar = "" |
VBA.Constants 的成員
那么下面這段代碼代表什么呢?
海蛇給出了它的代碼
| Dim s1 As String Dim s2 As String Dim s3 As String s1 = vbNullString s2 = vbNullChar s3 = "" Debug.Print StrPtr(s1), StrPtr(s2), StrPtr(s3) Debug.Print LenB(s1), LenB(s2), LenB(s3) |
天下第七帥按下F5后,他很驚訝海蛇代碼的運行結果
0 1899284 1434596
0 2 0
那么就是說VB的說明和海蛇之間一定有人錯了。而且,對于采用S1兩個值都是零,指針指向零,長度為零,它不是一個普通意義上的零值呀。
天下第七帥于是轉過頭來看著我。
“小子,出風頭吧,來吧,我先給你們看點東西”
“你們想要打敗海蛇,就一定要了解海蛇的結構”
VB的字符串是一個標準的BSTR字符串,比如說”Hello”這個字符串它的結構是這樣的
| A | 0 | 0 | 0 | ‘H | 0 | ‘e’ | 0 | ‘l’ | 0 | ‘l’ | 0 | ‘o’ | 0 | 0 | 0 |
可以看到前面四個字節代表 字符串實際長度所占字節數,它是一個Long值。
而最后兩個字節是代表零值的結尾字符。
而中間的十個字節正好是字符串的內容。
如果我們用s1=”Hello”,那么s1是指向什么地方呢。
“最初我以為s1是指向第一個字節,但是當我用自編的VB內存觀測工具來看strptr(s1)后面所跟的字節值時發現,s1是指向第五個字節,也就是我們字符串真正開始的地方。”
“大家都了解了海蛇的結構了,那么它剛才提出的三種情況為什么會有不同呢?”我向還在發呆的下潛者。
“是呀,為什么?”
好了,拿出你們的OleView,在File-> View TypeLib中打開VB6.DLL,你是不是看到了一個很奇妙的天地,別發呆,找到以下部分
| Modules->Modules Constants |
打開他們你便會看到VB內部真正的定義了。
| [helpcontext(0x0010aa32)] const LPSTR vbNullString = ""; [helpcontext(0x0010aa32)] const LPSTR vbNullChar = ""; |
看到了沒有,vbNullString指向一個空字串,但這個空字串是零址的。而vbNullChar則是一個零字符(相當于C中字符串中最后一個字符)。那么我們來看海蛇的代碼運行時發生了什么
| s1 = vbNullString |
VB看到這句時,它很清楚把S1的值變成了零
| s2 = vbNullChar |
VB看到這句時,它做了幾個動作,它用SysAllocStringLen在堆中分配了一個BSTR字符串,然后將’’復制到這個字符串里。
| s3 = "" |
這里VB做了很多工作,首先,VB在編譯時,把""當成了一個常量,它必須為這個空字符串內部申請一個變量。當EXE文件加載后,也得把它設定一個地址,雖然它什么都不代表
是一個 00 00 00 00 00 00 這樣的字符串,它需要6個字節(四個頭字節和2個尾字節)
然后當看到這句時再把第五個字節的地址值傳給s3
所以,雖然你只是信手寫了一個"",結果VB多作了很多工作。6個字節雖然不多,但是在一個大工程里,大家都到處寫“”,那么也是很可觀的一筆開銷。所以下次你絕對不要再用"",而一定要用vbNullString
“你說,是么,海蛇”,我輕蔑地看著它。
海蛇看到大家都恍然大悟的樣子,再此發出了它的笑聲(海蛇會笑么?)
“了解我,并不是真正的掌控我,很多C的潛水員會對VB不屑一顧,你們知道是為什么?”
“慢,VB的字符串操作太慢了”很多潛水者都回搶著回答這個問題。
“呵呵,是的,”海蛇放聲大笑,慢慢地游向深海“I will Back!”
留下我們這群潛水的人,大家在思索,我們真正了解海蛇了么,因為VB海洋傳說中海蛇是相當可怕的,它會這么輕易地走開么,而且,它所說的 I will Back又是指什么?
但是我們會繼續下潛…….
“看,珊瑚礁”有人在驚呼!