bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

vb.net缺少調(diào)試目標的簡單介紹

vb.net中的if else問題

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),丘北企業(yè)網(wǎng)站建設(shè),丘北品牌網(wǎng)站建設(shè),網(wǎng)站定制,丘北網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,丘北網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。

If TextBox1.Focus Then : TextBox1.Text = Val(TextBox1.Text) * 10 + 1 : Else : TextBox3.Text = Val(TextBox3.Text) * 10 + 1 : End If

End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

If TextBox1.Focus Then

TextBox1.Text = Val(TextBox1.Text) * 10 + 1

Else

TextBox3.Text = Val(TextBox3.Text) * 10 + 1

End If

End Sub

樓主只是單純的格式錯誤而已。

If...Then... 是可以

If...Then...Else 是不存在的

需要一行內(nèi)用到的話,必須還要跟個End If,也就是

If...Then...Else...End If

當(dāng)然最好還是分行寫,自己以后修改也容易看

If 條件1 Then

' 代碼

ElseIf 條件2 Then

' 代碼

ElseIf 條件2 Then

' 代碼

Else

' 代碼

End If

其中ElseIf行與Else行,在不需要時都可以不寫。

.NET語言的選擇,C#,VB.Net哪個更有前途?

Visual Basic.net還是C#

——如何選擇.net語言

在.net中,如何選擇VB或C#?這似乎已經(jīng)爭論了很久。很多人盲目選擇,也產(chǎn)生了許多流言和錯誤。本文將從以下方面指導(dǎo)你選擇正確的開發(fā)語言。

功能上的考慮

許多人認為C#的功能比VB.net強大,或者C#更加適合.net等。其實這不是一兩句話能比較清楚的。C#的確有VB無法完成的功能,但VB也有C#無法完成的功能??偟膩碚f,對于.net開發(fā),VB和C#沒有任何差別,都100%兼容于CLS。下面列出的是他們語言功能上的不同,這些僅僅是語言實現(xiàn)上的問題,不會影響到生成的代碼。打*號的內(nèi)容與CLS不兼容。

C#有而VB沒有的功能:

1、 運算符重載。*

2、 不安全代碼(指針和固定內(nèi)存區(qū))。*

3、 無符號整數(shù)。*

4、 移位運算。

VB有而C#沒有的功能

1、 即時編譯。

2、 靜態(tài)事件綁定。

3、 條件異常捕獲。

4、 COM兼容類。*

5、 寬松的類型檢查和變量聲明。

6、 Visual Basic Runtime庫。

7、 可選參數(shù)、帶參數(shù)屬性、模塊等語言特征。*

8、 動態(tài)數(shù)組。*

可見,實際上功能更強大的是VB而不是C#。不過它們不一樣的地方多半是無關(guān)緊要的特征??傮w上來說,不應(yīng)從功能上選擇VB或者C#,因為他們沒有什么具體的差別。

性能上的考慮

性能是程序員最關(guān)心的問題。VB和C#都生成一樣的IL,因此理論上說不會有性能的差異。但許多人為什么說C#的性能高于VB.net呢?這是因為VB.net支持即時編譯,就是一邊書寫代碼一邊編譯。這樣可立刻發(fā)現(xiàn)語法錯誤,使調(diào)試變得更加容易。但是這樣一來VB就需要隨時瀏覽整個代碼文件,并把臨時數(shù)據(jù)儲存。這造成VB.net生成的代碼中常常具有冗余部分。但也不能就此下結(jié)論說VB比C#慢,當(dāng)用戶選擇打開優(yōu)化并且以Release方式編譯工程,就能得到與C#一樣簡短快速的代碼。

學(xué)習(xí)上的難度

這部分不僅僅初學(xué)者需要考慮,那些從現(xiàn)有開發(fā)工具轉(zhuǎn)移到.net的開發(fā)人員也需要考慮。首先,VB和C#都是非常簡單的,對于初學(xué)者來說,VB提供伸縮性更強的空間,因此比C#更加易于接受。但這只是相對而言,C#對于初學(xué)者來說也不會有太多的困難。

對于使用Visual Basic6或其他版本的程序員來說。VB.net的語法顯然要比C#更加接近VB6,網(wǎng)上流傳的VB與VB.net差別被過分夸大,使部分程序員退縮。其實VB.net增加的只是面向?qū)ο蟮乃枷?,許多VB程序員不具備完善的面向?qū)ο缶幊涕_發(fā)經(jīng)驗,因此覺得VB.net難以接受,這是很容易克服的。想想看,即使你要使用C#不也得學(xué)習(xí)面向?qū)ο髥??至于有C/C++/Java經(jīng)驗的人,C#是小菜一碟。剛才說過C#和VB實際上都很簡單,所以不見得VB程序員學(xué)習(xí)C#就要比C/C++程序員來的困難,反之亦然,有C/C++經(jīng)驗的人也可以果斷的選擇VB。

移植現(xiàn)有代碼

這一部分是程序員最頭疼的部分。但對語言選擇有決定性的意義。

從VB6移植代碼的程序員,最佳選擇就是VB.net,因為其他.net語言沒有一種是與VB相似的。而且即使VB6的工程移植到VB.net非常困難,也有一個移植向?qū)Э梢詭椭阃瓿纱蟛糠止ぷ鳌H绻止ぐ阉浦驳紺#,需要白白花費大量的時間。而且剛開始使用C#的VB程序員通常都會為C#缺少他們熟悉的函數(shù)而頭疼。VB.net不會出現(xiàn)這種情況。

從ASP移植到ASP.net,首選語言仍然是VB.net,因為多數(shù)程序員使用的ASP語言是VBScript,只有VB.net最大程度地接近這種語言。

C#對于移植代碼似乎沒有作用,了解C#的人都明白,把現(xiàn)有C/C++代碼放到C#中運行幾乎是100%不能通過的。所以,如果需要移植C/C++代碼,最好使用Visual C++.net。他做到了最好的新舊結(jié)合。C#僅僅用于編寫新的.net應(yīng)用程序。

如果需要從Java移植代碼,C#可以選擇。同時還有J#及其他一些MS提供的轉(zhuǎn)換工具。

文檔和資源方面的考慮

在MSDN文檔中,C#和VB是同等看待的。所有文檔和例子都是有VB和C#兩份的。因此,在尋求資源方面都不用擔(dān)心?;ヂ?lián)網(wǎng)上的資源,C#要多于VB,特別是國內(nèi),有傾向于C#的潮流。但是ASP.net的資源VB較多。國內(nèi)缺乏VB.net資源是影響VB.net推廣的重要原因。但是在國外有很多非常成熟的VB技術(shù),如掌上設(shè)備的開發(fā)技術(shù)。

代碼風(fēng)格和雜項問題

C#書寫的代碼比VB平均短小20%,許多人不喜歡VB中過長的關(guān)鍵字。當(dāng)然他們可以選擇C#。但在開發(fā)環(huán)境中,VB的自動完成功能比C#更完善,其實30%的代碼都是自動補充的。因此,實際上VB程序員不會比C#多打多少字。但VB語言換行比C#麻煩,如果需要書寫大量繁雜而長的代碼,最好選擇C#。VB的代碼接近完整的英語,比C#更加易讀。如果是初學(xué)者不妨選擇VB。

有關(guān)于VB對內(nèi)存讀寫的操作,那位幫幫忙

暈,眼都花了~~給你篇文章看看把,VB用指針操作內(nèi)存,就倆API

真沒想到VB也可以這樣用之指針技術(shù)

想當(dāng)年東方不敗,黑木崖密室一戰(zhàn),僅憑一根繡花針獨戰(zhàn)四大高手,神出鬼沒,堪稱天下武林第一高手。若想成為VB里的東方不敗,熟習(xí)VB《葵花寶典》,掌握VB指針技術(shù),乃是不二的法門。

欲練神功,引刀……,其實掌握VB指針技術(shù),并不需要那么痛苦。因為說穿了,也就那么幾招,再勤加練習(xí),終可至神出鬼沒之境。廢話少說,讓我們先從指針的定義說起。

一、指針是什么?

不需要去找什么標準的定義,它就是一個32位整數(shù),在C語言和在VB里都可以用Long類型來表示。在32位Windows平臺下它和普通的32位長整型數(shù)沒有什么不同,只不過它的值是一個內(nèi)存地址,正是因為這個整數(shù)象針一樣指向一個內(nèi)存地址,所以就有了指針的概念。

有統(tǒng)計表明,很大一部分程序缺陷和內(nèi)存的錯誤訪問有關(guān)。正是因為指針直接和內(nèi)存打交道,所以指針一直以來被看成一個危險的東西。以至于不少語言,如著名的JAVA,都不提供對指針操作的支持,所有的內(nèi)存訪問方面的處理都由編譯器來完成。而象C和C++,指針的使用則是基本功,指針給了程序員極大的自由去隨心所欲地處理內(nèi)存訪問,很多非常巧妙的東西都要依靠指針技術(shù)來完成。

關(guān)于一門高級的程序設(shè)計語言是不是應(yīng)該取消指針操作,關(guān)于沒有指針操作算不算一門語言的優(yōu)點,我在這里不討論,因為互聯(lián)網(wǎng)上關(guān)于這方面的沒有結(jié)果的討論,已經(jīng)造成了占用幾個GB的資源。無論最終你是不是要下定決心修習(xí)指針技術(shù)《葵花寶典》,了解這門功夫總是有益處的。

注意:在VB里,官方是不鼓勵使用什么指針的,本文所講的任何東西你都別指望取得官方的技術(shù)支持,一切都要靠我們自己的努力,一切都更刺激!

讓我們開始神奇的VB指針探險吧!

二、來看看指針能做什么?有什么用?

先來看兩個程序,程序的功能都是交換兩個字串:

【程序一】:

'標準的做法SwapStr

Sub SwapStr(sA As String, sB As String)

Dim sTmp As String

sTmp = sA: sA = sB: sB = sTmp

End Sub

【程序二】:

'用指針的做法SwapPtr

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (Destination As Any, Source As Any, ByVal Length As Long)

Sub SwapPtr(sA As String, sB As String)

Dim lTmp As Long

CopyMemory lTmp, ByVal VarPtr(sA), 4

CopyMemory ByVal VarPtr(sA), ByVal VarPtr(sB), 4

CopyMemory ByVal VarPtr(sB), lTmp, 4

End Sub

你是不是以為第一個程序要快,因為它看著簡單而且不用調(diào)用API(調(diào)用API需要額外的處理,VB文檔明確指出大量調(diào)用API將降低程序性能)。但事實上,在VB集成環(huán)境中運行,程序二要比程序一快四分之一;而編譯成本機代碼或p-code,程序二基本上要比程序一快一倍。下面是兩個函數(shù)在編譯成本機代碼后,運行不同次數(shù)所花時間的比較:

運行100000次,SwapStr需要170毫秒,SwapPtr需要90毫秒。

運行200000次,SwapStr需要340毫秒,SwapPtr需要170毫秒。

運行2000000次,SwapStr需要3300毫秒,SwapPtr需要1500毫秒。

的確,調(diào)用API是需要額外指令來處理,但是由于使用了指針技術(shù),它沒有進行臨時字串的分配和拷貝,因此速度提高了不少。

怎么樣,想不到吧!C/C++程序員那么依賴指針,無非也是因為使用指針往往能更直接的去處理問題的根源,更有駕馭一切的快感。他們不是不知道使用指針的危險,他們不是不愿意開衛(wèi)星定位無級變速的汽車,只是騎摩托更有快感,而有些地方只有摩托才走得過去。

和在C里類似,在VB里我們使用指針也不過三個理由:

一是效率,這是一種態(tài)度一種追求,在VB里也一樣;

二是不能不用,因為操作系統(tǒng)是C寫的,它時刻都在提醒我們它需要指針;

三是突破限制,VB想照料我們的一切,VB給了我們很強的類型檢查,VB象我們老媽一樣,對我們關(guān)心到有時我們會受不了,想偶爾不聽媽媽的話嗎?你需要指針!

但由于缺少官方的技術(shù)支持,在VB里,指針變得很神秘。因此在C里一些基本的技術(shù),在VB里就變得比較困難。本文的目的就是要提供給大家一種簡單的方法,來將C處理指針的技術(shù)拿到VB里來,并告訴你什么是可行的,什么可行但必須要小心的,什么是可能但不可行的,什么是根本就不可能的。

三、 程咬金的三板斧

是的,程序二基本上就已經(jīng)讓我們看到VB指針技術(shù)的模樣了??偨Y(jié)一下,在VB里用指針技術(shù)我們需要掌握三樣?xùn)|西:CopyMemory,VarPtr/StrPtr/ObjPtr, AdressOf. 三把斧頭,程咬金的三板斧,在VB里Hack的工具。

1、CopyMemory

關(guān)于CopyMemory和Bruce McKinney大師的傳奇,MSDN的Knowledge Base中就有文章介紹,你可以搜索"ID: Q129947"的文章。正是這位大師給32位的VB帶來了這個可以移動內(nèi)存的API,也正是有了這個API,我們才能利用指針完成我們原來想都不敢想的一些工作,感謝Bruce McKinney為我們帶來了VB的指針革命。

如CopyMemory的聲明,它是定義在Kernel32.dll中的RtlMoveMemory這個API,32位C函數(shù)庫中的memcpy就是這個API的包裝,如MSDN文檔中所言,它的功能是將從Source指針所指處開始的長度為Length的內(nèi)存拷貝到Destination所指的內(nèi)存處。它不會管我們的程序有沒有讀寫該內(nèi)存所應(yīng)有的權(quán)限,一但它想讀寫被系統(tǒng)所保護的內(nèi)存時,我們就會得到著名的Access Violation Fault(內(nèi)存越權(quán)訪問錯誤),甚至?xí)鸶膅eneral protection (GP) fault(通用保護錯誤) 。所以,在進行本系列文章里的實驗時,請注意隨時保存你的程序文件,在VB集成環(huán)境中將"工具"-"選項"中的"環(huán)境"選項卡里的"啟動程序時"設(shè)為"保存改變",并記住在"立即"窗口中執(zhí)行危險代碼之前一定要保存我們的工作成果。

2、VatPtr/StrPtr/ObjPtr

它們是VB提供給我們的好寶貝,它們是VBA函數(shù)庫中的隱藏函數(shù)。為什么要隱藏?因為VB開發(fā)小組,不鼓勵我們用指針嘛。

實際上這三個函數(shù)在VB運行時庫MSVBVM60.DLL(或MSVBVM50.DLL)中是同一個函數(shù)VarPtr(可參見我在本系列第一篇文章里介紹的方法)。

其庫型庫定義如下:

[entry("VarPtr"), hidden]

long _stdcall VarPtr([in] void* Ptr);

[entry("VarPtr"), hidden]

long _stdcall StrPtr([in] BSTR Ptr);

[entry("VarPtr"), hidden]

long _stdcall ObjPtr([in] IUnknown* Ptr);

即然它們是VB運行時庫中的同一個函數(shù),我們也可以在VB里用API方式重新聲明這幾個函數(shù),如下:

Private Declare Function ObjPtr Lib "MSVBVM60" Alias "VarPtr" (var As Object) As Long

Private Declare Function VarPtr Lib "MSVBVM60" (var As Any) As Long

(沒有StrPtr,是因為VB對字符串處理方式有點不同,這方面的問題太多,我將在另一篇文章中詳談。順便提一下,聽說VB.NET里沒有這幾個函數(shù),但只要還能調(diào)用API,我們就可以試試上面的幾個聲明,這樣在VB.NET里我們一樣可以進行指針操作。但是請注意,如果通過API調(diào)用來使用VarPtr,整個程序二SwapPtr將比原來使用內(nèi)置VarPtr函數(shù)時慢6倍。)

如果你喜歡刨根問底,那么下面就是VarPtr函數(shù)在C和匯編語言里的樣子:

在C里樣子是這樣的:

long VarPtr(void* pv){

return (long)pv;

}

所對就的匯編代碼就兩行:

mov eax,dword ptr [esp+4]

ret 4 '彈出棧里參數(shù)的值并返回。

之所以讓大家了解VarPtr的具體實現(xiàn),是想告訴大家它的開銷并不大,因為它們不過兩條指令,即使加上參數(shù)賦值、壓棧和調(diào)用指令,整個獲取指針的過程也就六條指令。當(dāng)然,同樣的功能在C語言里,由于語言的直接支持,僅需要一條指令即可。但在VB里,它已經(jīng)算是最快的函數(shù)了,所以我們完全不用擔(dān)心使用VarPtr會讓我們失去效率!速度是使用指針技術(shù)的根本要求。

一句話,VarPtr返回的是變量所在處的內(nèi)存地址,也可以說返回了指向變量內(nèi)存位置的指針,它是我們在VB里處理指針最重要的武器之一。

3、ByVal和ByRef

ByVal傳遞的參數(shù)值,而ByRef傳遞的參數(shù)的地址。在這里,我們不用去區(qū)別傳指針/傳地址/傳引用的不同,在VB里,它們根本就是一個東西的三種不同說法,即使VB的文檔里也有地方在混用這些術(shù)語(但在C++里的確要區(qū)分指針和引用)

初次接觸上面的程序二SwapPtr的朋友,一定要搞清在里面的CopyMemory調(diào)用中,在什么地方要加ByVal,什么地方不加(不加ByVal就是使用VB缺省的ByRef),準確的理解傳值和傳地址(指針)的區(qū)別,是在VB里正確使用指針的基礎(chǔ)。

現(xiàn)在一個最簡單的實驗來看這個問題,如下面的程序三:

【程序三】:

'體會ByVal和ByRef

Sub TestCopyMemory()

Dim k As Long

k = 5

Note: CopyMemory ByVal VarPtr(k), 40000, 4

Debug.Print k

End Sub

上面標號Note處的語句的目的,是將k賦值為40000,等同于語句k=40000,你可以在"立即"窗口試驗一下,會發(fā)現(xiàn)k的值的確成了40000。

實際上上面這個語句,翻譯成白話,就是從保存常數(shù)40000的臨時變量處拷貝4個字節(jié)到變量k所在的內(nèi)存中。

現(xiàn)在我們來改變一個Note處的語句,若改成下面的語句:

Note2: CopyMemory ByVal VarPtr(k), ByVal 40000, 4

這句話的意思就成了,從地址40000拷貝4個字節(jié)到變量k所在的內(nèi)存中。由于地址40000所在的內(nèi)存我們無權(quán)訪問,操作系統(tǒng)會給我們一個Access Violation內(nèi)存越權(quán)訪問錯誤,告訴我們"試圖讀取位置0x00009c40處內(nèi)存時出錯,該內(nèi)存不能為'Read'"。

我們再改成如下的語句看看。

Note3: CopyMemory VarPtr(k), 40000, 4

這句話的意思就成了,從保存常數(shù)40000的臨時變量處拷貝4個字節(jié)到到保存變量k所在內(nèi)存地址值的臨時變量處。這不會出出內(nèi)存越權(quán)訪問錯誤,但k的值并沒有變。

我們可以把程序改改以更清楚的休現(xiàn)這種區(qū)別,如下面的程序四:

【程序四】:

'看看我們的東西被拷貝到哪兒去了

Sub TestCopyMemory()

Dim i As Long, k As Long

k = 5

i = VarPtr(k)

NOTE4: CopyMemory i, 40000, 4

Debug.Print k

Debug.Print i

i = VarPtr(k)

NOTE5: CopyMemory ByVal i, 40000, 4

Debug.Print k

End Sub

程序輸出:

5

40000

40000

由于NOTE4處使用缺省的ByVal,傳遞的是i的地址(也就是指向i的指針),所以常量40000拷貝到了變量i里,因此i的值成了40000,而k的值卻沒有變化。但是,在NOTE4前有:i=VarPtr(k),本意是要把i本身做為一個指針來使用。這時,我們必須如NOTE5那樣用ByVal來傳遞指針i,由于i是指向變量k的指針,所以最后常量40000被拷貝了變量k里。

希望你已經(jīng)理解了這種區(qū)別,在后面問題的討論中,我還會再談到它。

4、AddressOf

它用來得到一個指向VB函數(shù)入口地址的指針,不過這個指針只能傳遞給API使用,以使得API能回調(diào)VB函數(shù)。

本文不準備詳細討論函數(shù)指針,關(guān)于它的使用請參考VB文檔。

5、拿來主義

實際上,有了CopyMemory,VarPtr,AddressOf這三把斧頭,我們已經(jīng)可以將C里基本的指針操作拿過來了。

如下面的C程序包括了大部分基本的指針指針操作:

struct POINT{

int x; int y;

};

int Compare(void* elem1, void* elem2){}

void PtrDemo(){

//指針聲明:

char c = 'X'; //聲明一個char型變量

char* pc; long* pl; //聲明普通指針

POINT* pPt; //聲明結(jié)構(gòu)指針

void* pv; //聲明無類型指針

int (*pfnCastToInt)(void *, void*);//聲明函數(shù)指針:

//指針賦值:

pc = c; //將變量c的地址值賦給指針pc

pfnCompare = Compare; //函數(shù)指針賦值。

//指針取值:

c = *pc; //將指針pc所指處的內(nèi)存值賦給變量c

//用指針賦值:

*pc = 'Y' //將'Y'賦給指針pc所指內(nèi)存變量里。

//指針移動:

pc++; pl--;

}

這些對指針操作在VB里都有等同的東西,前面討論ByVal和ByRef時曾說過傳指針和傳地址是一回事,實際上當(dāng)我們在VB里用缺省的ByRef聲明函數(shù)參數(shù)時,我們已經(jīng)就聲明了指針。

如一個C聲明的函數(shù):long Func(char* pc)

其對應(yīng)的VB聲明是:Function Func(pc As Byte) As Long

這時參數(shù)pc使用缺省的ByRef傳地址方式來傳遞,這和C里用指針來傳遞參數(shù)是一樣。

那么怎么才能象C里那樣明確地聲明一個指針呢?

很簡單,如前所說,用一個32位長整數(shù)來表達指針就行。在VB里就是用Long型來明確地聲明指針,我們不用區(qū)分是普通指針、無類型指針還是函數(shù)指針,通通都可用Long來聲明。而給一個指針賦值,就是賦給它用VarPar得到的另一個變量的地址。具體見程序五。

【程序五】:同C一樣,各種指針。

Type POINT

X As Integer

Y As Integer

End Type

Public Function Compare(elem1 As Long, elem2 As Long) As Long

'

End Function

Function FnPtrToLong(ByVal lngFnPtr As Long) As Long

FnPtrToLong = lngFnPtr

End Function

Sub PtrDemo()

Dim l As Long, c As Byte, ca() As Byte, Pt As POINT

Dim pl As Long, pc As Long, pv As Long, pPt As Long, pfnCompare As Long

c = AscB("X")

pl = VarPtr(l) '對應(yīng)C里的long、int型指針

pc = VarPtr(c) '對應(yīng)char、short型指針

pPt = VarPtr(Pt) '結(jié)構(gòu)指針

pv = VarPtr(ca(0)) '字節(jié)數(shù)組指針,可對應(yīng)任何類型,也就是void*

pfnCompare = FnPtrToLong(AddressOf Compare) '函數(shù)指針

CopyMemory c, ByVal pc, LenB(c) '用指針取值

CopyMemory ByVal pc, AscB("Y"), LenB(c) '用指針賦值

pc = pc + LenB(c) : pl = pl - LenB(l) '指針移動

End Sub

我們看到,由于VB不直接支持指針操作,在VB里用指針取值和用指針賦值都必須用CopyMemory這個API,而調(diào)用API的代價是比較高的,這就決定了我們在VB里使用指針不能象在C里那樣自由和頻繁,我們必須要考慮指針操作的代價,在后面的"指針應(yīng)用"我們會再變談這個問題。

程序五中關(guān)于函數(shù)指針的問題請參考VB文檔,無類型指針void*會在下面"關(guān)于Any的問題"里說。

程序五基本上已經(jīng)包括了我們能在VB里進行的所有指針操作,僅此而已。

下面有一個小測試題,如果現(xiàn)在你就弄懂了上面程咬金的三板斧,你就應(yīng)該能做得出來。

上面提到過,VB.NET中沒有VarPtr,我們可以用聲明API的方式來引入MSVBVM60.DLL中的VarPtr?,F(xiàn)在的問題如果不用VB的運行時DLL文件,你能不能自己實現(xiàn)一個ObjPtr。答案在下一節(jié)后給出。

四、指針使用中應(yīng)注意的問題

1、關(guān)于ANY的問題

如果以一個老師的身份來說話,我會說:最好永遠也不要用Any!是的,我沒說錯,是永遠!所以我沒有把它放在程咬金的三板斧里。當(dāng)然,這個問題和是不是應(yīng)該使用指針這個問題一樣會引發(fā)一場沒有結(jié)果的討論,我告訴你的只是一個觀點,因為有時我們會為了效率上的一點點提高或想偷一點點懶而去用Any,但這樣做需要要承擔(dān)風(fēng)險。

Any不是一個真正的類型,它只是告訴VB編譯器放棄對參數(shù)類型的檢查,這樣,理論上,我們可以將任何類型傳遞給API。

Any在什么地方用呢?讓我們來看看,在VB文檔里的是怎么說的,現(xiàn)在就請打開MSDN(Visual Studio 6自帶的版本),翻到"Visual Basic文檔"-"使用Visual Basic"-"部件工具指南"-"訪問DLL和Windows API"部分,再看看"將 C 語言聲明轉(zhuǎn)換為 Visual Basic 聲明"這一節(jié)。文檔里告訴我們,只有C的聲明為LPVOID和NULL時,我們才用Any。實際上如果你愿意承擔(dān)風(fēng)險,所有的類型你都可以用Any。當(dāng)然,也可以如我所說,永遠不要用Any。

為什么要這樣?那為什么VB官方還要提供Any?是信我的,還是信VB官方的?有什么道理不用Any?

如前面所說,VB官方不鼓勵我們使用指針。因為VB所標榜的優(yōu)點之一,就是沒有危險的指針操作,所以的內(nèi)存訪問都是受VB運行時庫控制的。在這一點上,JAVA語言也有著同樣的標榜。但是,同JAVA一樣,VB要避免使用指針而得到更高的安全性,就必須要克服沒有指針而帶來的問題。VB已經(jīng)盡最大的努力來使我們遠離指針的同時擁有強類型檢查帶來的安全性。但是操作系統(tǒng)是C寫的,里面到處都需要指針,有些指針是沒有類型的,就是C程序員常說的可怕的void*無類型指針。它沒有類型,因此它可以表示所有類型。如CopyMemory所對應(yīng)的是C語言的memcpy,它的聲明如下:

void *memcpy( void *dest, const void *src, size_t count );

因memcpy前兩個參數(shù)用的是void*,因此任何類型的參數(shù)都可以傳遞給他。

一個用C的程序員,應(yīng)該知道在C函數(shù)庫里這樣的void*并不少見,也應(yīng)該知道它有多危險。無論傳遞什么類型的變量指針給上面memcpy的void*,C編譯器都不會報錯或給任何警告。

在VB里大多數(shù)時候,我們使用Any就是為了使用void*,和在C里一樣,VB也不對Any進行類型檢查,我們也可以傳遞任何類型給Any,VB編譯器也都不會報錯或給任何警告。

但程序運行時會不會出錯,就要看使用它時是不是小心了。正因為在C里很多錯誤是和void*相關(guān)的,所以,C++鼓勵我們使用satic_castvoid*來明確指出這種不安全的類型的轉(zhuǎn)換,已利于發(fā)現(xiàn)錯誤。

說了這么多C/C++,其實我是想告訴所有VB的程序員,在使用Any時,我們必須和C/C++程序員使用void*一樣要高度小心。

VB里沒有satic_cast這種東西,但我們可以在傳遞指針時明確的使用long類型,并且用VarPtr來取得參數(shù)的指針,這樣至少已經(jīng)明確地指出我們在使用危險的指針。如程序二經(jīng)過這樣的處理就成了下面的程序:

【程序五】:

'使用更安全的CopyMemory,明確的使用指針!

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)

Sub SwapStrPtr2(sA As String, sB As String)

Dim lTmp As Long

Dim pTmp As Long, psA As Long, psB As Long

pTmp = VarPtr(lTmp): psA = VarPtr(sA): psB = VarPtr(sB)

CopyMemory pTmp, psA, 4

CopyMemory psA, psB, 4

CopyMemory psB, pTmp, 4

End Sub

注意,上面CopyMemory的聲明,用的是ByVal和long,要求傳遞的是32位的地址值,當(dāng)我們將一個別的類型傳遞給這個API時,編譯器會報錯,比如現(xiàn)在我們用下面的語句:

【程序六】:

'有點象【程序四】,但將常量40000換成了值為1的變量.

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, Length As Long)

Sub TestCopyMemory()

Dim i As Long,k As Long, z As Interger

k = 5 : z = 1

i = VarPtr(k)

'下面的語句會引起類型不符的編譯錯誤,這是好事!

'CopyMemory i, z, 4

'應(yīng)該用下面的

CopyMemory i, ByVal VarPtr(z), 2

Debug.Print k

End Sub

編譯會出錯!是好事!這總比運行時不知道錯在哪兒好!

象程序四那樣使用Any類型來聲明CopyMemory的參數(shù),VB雖然不會報錯,但運行時結(jié)果卻是錯的。不信,你試試將程序四中的40000改為1,結(jié)果i的值不是我們想要的1,而是327681。為什么在程序四中,常量為1時結(jié)果會出錯,而常量為40000時結(jié)果就不錯?

原因是VB對函數(shù)參數(shù)中的常量按Variant的方式處理。是1時,由于1小于Integer型的最大值32767,VB會生成一個存儲值1的Integer型的臨時變量,也就是說,當(dāng)我們想將1用CopyMemroy拷貝到Long型的變量i時,這個常量1是實際上是Integer型臨時變量!VB里Integer類型只有兩個字節(jié),而我們實際上拷貝了四個字節(jié)。知道有多危險了吧!沒有出內(nèi)存保護錯誤那只是我們的幸運!

如果一定要解釋一下為什么i最后變成了327681,這是因為我們將k的低16位的值5也拷貝到了i值的高16位中去了,因此有5*65536+1=327681。詳談這個問題涉及到VB局部變量聲明順序,CopyMemory參數(shù)的壓棧順序,long型的低位在前高位在后等問題。如果你對這些問題感興趣,可以用本系列第一篇文章所提供的方法(DebugBreak這個API和VC調(diào)試器)來跟蹤一下,可以加深你對VB內(nèi)部處理方式的認識,由于這和本文討論的問題無關(guān),所以就不詳談了。到這里,大家應(yīng)該明白,程序三和程序四實際上有錯誤?。。∥以谏厦嬗贸A?0000而不用1,不是為了在文章中湊字數(shù),而是因為40000這個常量大于32767,會被VB解釋成我們需要的Long型的臨時變量,只有這樣程序三和程序四才能正常工作。對不起,我這樣有意的隱藏錯誤只是想加深你對Any危害的認識。

總之,我們要認識到,編譯時就找到錯誤是非常重要的,因為你馬上就知道錯誤的所在。所以我們應(yīng)該象程序五和程序六那樣明確地用long型的ByVal的指針,而不要用Any的ByRef的指針。

但用Any已經(jīng)如此的流行,以至很多大師們也用它。它唯一的魅力就是不象用Long型指針那樣,需要我們自己調(diào)用VarPtr來得到指針,所有處理指針的工作由VB編譯器來完成。所以在參數(shù)的處理上,只用一條匯編指令:push ,而用VarPtr時,由于需要函數(shù)調(diào)用,因此要多用五條匯編指令。五條多余的匯編指令有時的確能我們冒著風(fēng)險去用Any。

VB開發(fā)小組提供Any,就是想用ByRef xxx As Any來表達void* xxx。我們也完全可以使用VarPtr和Long型的指針來處理。我想,VB開發(fā)小組也曾猶豫過是公布VarPtr,還是提供Any,最后他們決定還是提供Any,而繼續(xù)隱瞞VarPtr。的確,這是個兩難的決定。但是經(jīng)過我上面的分析,我們應(yīng)該知道,這個決定并不符合VB所追求的"更安全"的初衷。因為它可能會隱藏類型不符的錯誤,調(diào)試和找到這種運行時才產(chǎn)生的錯誤將花貴更多的時間和精力。

所以我有了"最好永遠不要用Any"這個"驚人"的結(jié)論。

不用Any的另一個好處是,簡化了我們將C聲明的API轉(zhuǎn)換成VB聲明的方式,現(xiàn)在它變成了一句話:除了VB內(nèi)置的可以進行類型檢查的類型外,所以其它的類型我們都應(yīng)該聲明成Long型。

2、關(guān)于NULL的容易混淆的問題

有很多文章講過,一定要記在心里:

VbNullChar 相當(dāng)于C里的'\0',在用字節(jié)數(shù)組構(gòu)造C字串時常用它來做最后1個元素。

vbNullString 這才是真正的NULL,就是0,在VB6中直接用0也可以。

只有上面的兩個是API調(diào)用中會用的。還有Empty、Null是Variant,而Nothing只和類對象有關(guān),一般API調(diào)用中都不會用到它們。

另:本文第三節(jié)曾提出一個小測驗題,做出來了嗎?現(xiàn)在公布正確答案:

【測驗題答案】

Function ObjPtr(obj as Object) as long

Dim lpObj As Long

CopyMemory lpObj, Obj, 4

ObjectPtr = lpObj

End Function

五、VB指針應(yīng)用

如前面所說VB里使用指針不象C里那樣靈活,用指針處理數(shù)據(jù)時都需要用CopyMemory將數(shù)據(jù)在指針和VB能夠處理的變量之間來回拷貝,這需要很大的額外開銷。因此不是所有C里的指針操作都可以移值到VB里來,我們只應(yīng)在需要的時候才在VB里使用指針。

1、動態(tài)內(nèi)存分配:完全不可能、可能但不可行,VB標準

在C和C++里頻繁使用指針的一個重要原因是需要使用動態(tài)內(nèi)存分配,用Malloc或New來從堆棧里動態(tài)分配內(nèi)存,并得到指向這個內(nèi)存的指針。在VB里我們也可以自己

用API來實現(xiàn)動態(tài)分配內(nèi)存,并且實現(xiàn)象C里的指針鏈表。

但我們不可能象C那樣直接用指針來訪問這樣動態(tài)分配的內(nèi)存,訪問時我們必須用CopyMemory將數(shù)據(jù)拷貝到VB的變量內(nèi),大量的使用這種技術(shù)必然會降低效率,以至于要象C那樣用指針來使用動態(tài)內(nèi)存根本就沒有可行性。要象C、PASCAL那樣實現(xiàn)動態(tài)數(shù)據(jù)結(jié)構(gòu),在VB里還是應(yīng)該老老實實用對象技術(shù)來實現(xiàn)。

本文配套代碼中的LinkedList里有完全用指針實現(xiàn)的鏈表,它是使用HeapAlloc從堆棧中動態(tài)分配內(nèi)存,另有一個調(diào)用FindFirstUrlCacheEntry這個API來操作IE的Cache的小程序IECache,它使用了VirtualAlloc來動態(tài)分配內(nèi)存。但實際上這都不是必須的,VB已經(jīng)為我們提供了標準的動態(tài)內(nèi)存分配的方法,那就是:

對象、字符串和字節(jié)數(shù)組

限于篇幅,關(guān)于對象的技術(shù)這里不講,LinkedList的源代碼里有用對象實現(xiàn)的鏈表,你可以參考。

字符串可以用Space$函數(shù)來動態(tài)分配,VB的文檔里就有詳細的說明。

關(guān)于字節(jié)數(shù)組,這里要講講,它非常有用。我們可用Redim來動態(tài)改變它的大小,并將指向它第一個元素的指針傳給需要指針的API,如下:

dim ab() As Byte , ret As long

'傳遞Null值A(chǔ)PI會返回它所需要的緩沖區(qū)的長度。

ret = SomeApiNeedsBuffer(vbNullString)

'動態(tài)分配足夠大小的內(nèi)存緩沖區(qū)

ReDim ab(ret) As Byte

'再次把指針

VB.net 和C#.net 各有什么優(yōu)缺點

C#.net優(yōu)點:

運算符重載。不安全代碼(指針和固定內(nèi)存區(qū))、?無符號整數(shù)、移位運算。

VB的優(yōu)點:?

即時編譯、靜態(tài)事件綁定、條件異常捕獲、COM兼容類、寬松的類型檢查和變量聲明、Visual Basic Runtime庫、可選參數(shù)、帶參數(shù)屬性、模塊等語言特征、動態(tài)數(shù)組。

通過VB.NET開發(fā)好的程序絕對沒有問題(包括Direct X游戲開發(fā))。雖然VB.NET的資料少,但是只要C#支持的VB.NET都支持(大體上這樣,因為都要經(jīng)過MSIL中間環(huán)節(jié)。除了指針之類的VB.NET不支持C#支持,但是沒有多大實際用處)。

vb.net的資料以英文資料居多(只有英文資料才有看頭,中國的沒有什么好資料),得看看英文水平過不過關(guān)。還有VB.NET的ide也比C#的IDE好得多,代碼看得也舒服。(C#的大括號{}太煩人)。

至于VB6對C的幫助,只是理解上會容易一些,其它用處不大。有VB6的基礎(chǔ)學(xué)VBNET會方便一些,但是并不是會VB6就會VB.NET,它們差別也不小。

擴展資料:

NET、C#和ASP.NET之間的區(qū)別 :

1、NET是一個平臺,一個抽象的平臺的概念。

NET 平臺其本身實現(xiàn)的方式其實還是庫,抽象層面上來看是一個平臺。

基本可以理解的NET核心就是NETFramwork。

NETFramework包括兩個關(guān)鍵組成元素:

a. CommonLanguageRuntime,公共語言運行時(CLR0)-提供內(nèi)在管理,代碼安全性檢測等功能。

b. NETFrameworkClassLibrary,.NET 框架類庫(FLC)-提供大量應(yīng)用類庫,提高開發(fā)效率。

學(xué)習(xí)NET Framework 是所有.NET開發(fā)人員都必須的,否則開發(fā)NET程序永遠都是停留在‘外功’的招式,NETramework 是NET開發(fā)高手的‘內(nèi)功’修行之一。

2、C#是一個程序設(shè)計語言,僅僅是一個語言。

程序設(shè)計語言僅僅是為了方便開發(fā)人員和計算機溝通的工具,雖然 C#語法相對 C 和?C+要多一些,但是相對來看 C#語法都比較固定,這樣使用起來卻都很容易。我認可一位朋友說的,C#的語法更嚴謹!

這里回過來看看NET和C#的關(guān)系,不得不提的是NET程序的執(zhí)行過程。

C#符合NETCLR 中的公共語言運行規(guī)范。CLS:commonlanguagespecification,當(dāng)然所有的NET Language 都是符合這個規(guī)范的例如:VB.NET、XAML 和 C++/CL等等。

C#需要符合NETCLS,是因為NETCLR和JAVA虛擬機類似,有一個中間語言共機器來執(zhí)行。所有不同語言的.NET代碼在執(zhí)行前會被編譯成同樣的中間語言(MSIL),所以所有NET 支持語言都必須符合符合CLS 規(guī)范。

P.S:如果做.NET3.0XAML開發(fā)的朋友,可以嘗試下ildasm.exe看看XAML的應(yīng)用程序,會發(fā)現(xiàn)原來 XAML其實很簡單。

3、ASP.NET是一個網(wǎng)站開發(fā)的技術(shù),僅僅是.NET框架中的一個應(yīng)用模型。

用微軟公司ASP.NET快速入門中的一句話來解釋,ASP.NET是用于生成基于Web的應(yīng)用程序的內(nèi)容豐富的編程框架。

ASP.net 和C#的區(qū)別:

編寫asp.net通常包括兩部分的代碼:網(wǎng)頁層和后臺處理層,網(wǎng)頁就是用標記語言來寫的,而網(wǎng)頁對應(yīng)的后臺處理程序則需要.net語言來完成,目前主要是采用c#和vb.net。

可以說整個的asp.net網(wǎng)站通過c#或者vb.net來實現(xiàn)。而c#則是ms .netframework的主要語言,可以用在網(wǎng)站,桌面應(yīng)用等方面。可以算是一種比較流行的編程語言。

當(dāng)前標題:vb.net缺少調(diào)試目標的簡單介紹
分享URL:http://vcdvsql.cn/article42/ddopehc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、Google云服務(wù)器、定制網(wǎng)站、ChatGPT、企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化