国产不卡视频一区,国产专区欧美精品,91豆花视频在线播放http://www.bjzhda.cnzh-cn曙海教育集團(tuán)論壇http://www.bjzhda.cnRss Generator By Dvbbs.Netofficeoffice@126.comimages/logo.gif曙海教育集團(tuán)論壇Visual C++ 1.0:C++編譯器的終結(jié)者http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2446&Page=1wangxinxin2010-12-10 15:34:57
  Visual C++的發(fā)展與C/C++語言、Windows的歷程是分不開的。

  在C語言推出之前,操作系統(tǒng)等系統(tǒng)軟件主要是用匯編語言編寫的(如UNIX操作系統(tǒng))。由于匯編語言依賴于計(jì)算機(jī)硬件,因此程序的可移植性和可讀性就比較差。為了提高程序的可讀性和可移植性,并能實(shí)現(xiàn)匯編語言的某些功能(如匯編語言可以直接對(duì)硬件進(jìn)行操作、對(duì)內(nèi)存地址進(jìn)行操作和位操作等)。于是,C語言便應(yīng)運(yùn)而生了。

  最初的C語言只是為描述和實(shí)現(xiàn)UNIX操作系統(tǒng)而提供的一種程序設(shè)計(jì)語言。1973年,貝爾實(shí)驗(yàn)室的K.Thompson和D.M.Ritchie兩人合作把UNIX的90%以上的代碼用C語言改寫(即UNIX第五版)。后來C語言又作了多次改進(jìn),1978年以后,C語言已先后移植到大、中、小及微型機(jī)上,現(xiàn)在C語言已成為風(fēng)靡全球的計(jì)算機(jī)程序設(shè)計(jì)語言。

  到了80年代,美國AT&T貝爾實(shí)驗(yàn)室的Bjarne Stroustrup在C語言的基礎(chǔ)上推出了C++程序設(shè)計(jì)語言。由于C++提出了把數(shù)據(jù)和在數(shù)據(jù)之上的操作封裝在一起的類、對(duì)象和方法的機(jī)制,并通過派生、繼承、重載和多態(tài)性等特征,實(shí)現(xiàn)了人們期待已久的軟件復(fù)用和自動(dòng)生成。這使得軟件,特別是大型復(fù)雜軟件的構(gòu)造和維護(hù)變得更加有效和容易,并使軟件開發(fā)能更自然地反映事物的本質(zhì),從而大大提高了軟件的開發(fā)效率和質(zhì)量。

  在C/C++發(fā)展過程中,C/C++的開發(fā)工具也是發(fā)展迅速。

  早期的程序員仍然不會(huì)忘記Turbo Pascal的集成開發(fā)環(huán)境IDE的魅力,IDE能使編輯器和編譯器共同工作,在編輯器中寫下源代碼,使用Compile(編譯)命令來啟動(dòng)編譯器,當(dāng)編譯器發(fā)現(xiàn)錯(cuò)誤時(shí),它將編輯光標(biāo)定位到出錯(cuò)語句處,以便于改正。IDE為程序開發(fā)提供一個(gè)整體環(huán)境。

  C語言產(chǎn)生后,Turbo Pascal發(fā)行了Turbo C,Microsoft相應(yīng)地推出Quick C。雖然Quick C和Turbo C給C編程引進(jìn)許多內(nèi)容,但卻沒有對(duì)開發(fā)者產(chǎn)生永久性的影響(盡管Turbo C目前仍被用于現(xiàn)行教學(xué)中),其主要原因是二者的編輯器都不怎么好(Quick C編輯器后來合并到Microsoft Quick Basic中,現(xiàn)在它作為DOS編輯器Edit.com仍存在于Microsoft Windows 95中),其次,DOS下IDE占據(jù)大量?jī)?nèi)存,使程序運(yùn)行空間變得很小。

  編輯器之爭(zhēng)

  Visual C++在目前的C/C++編輯器占統(tǒng)治地位不是偶然的,這是由微軟的正確和對(duì)手的錯(cuò)誤造成。

  翻開C/C++編輯器歷史,戰(zhàn)火風(fēng)云。當(dāng)Microsoft Visual C++ 1.0 在C/C++開發(fā)工具市場(chǎng)獲得了空前的成功之后,Borland的Philippe Kahn也許在和Microsoft的FoxPro For Window一役中被嚇到了,因此急于在Visual C/C++ 1.0之后立刻推出新的Borland C/C++以扳回顏面。由于當(dāng)時(shí)Borland失去了許多的人才,Borland C/C++ 4.0倉促推出后,由于沒有在最后階段修正許多的錯(cuò)誤,加上加入太多的先進(jìn)技術(shù),造成了整個(gè)產(chǎn)品的不穩(wěn)定,從而鑄成大錯(cuò),陷入窘境。

  在Borland C/C++ 4.0失利之后,Borland為挽回局面,立刻著手開發(fā)Borland C/++ 4.0的Patch,當(dāng)時(shí)是稱為Service Pack。但是在4.01版中并沒有完全的解決問題,一直要到4.02才稍為解決一些嚴(yán)重的問題,無奈市場(chǎng)已經(jīng)起了巨大的變化。

  自Borland C/C++ 4.0一役大敗之后,Visual C/C++雖取得了勝利,但此時(shí)在C/C++市場(chǎng)上也加入了另外兩個(gè)堅(jiān)強(qiáng)的對(duì)手,那就是Symantec C/C++和Watcom C/C++。

  Symantec C/C++的Think C/C++在Macintosh上便是非常有名的編譯器,因此早在C/C++領(lǐng)域便有深厚的基礎(chǔ)。在Symantec并購了PC上第一個(gè)C/C++編譯器Zortech C/C++之后,Symantec決定進(jìn)入了PC的開發(fā)工具市場(chǎng)。恰逢Borland C/C++ 3.1的幕后支柱Eugene Wang剛好和Philippe Kahn鬧翻,離開了Borland。Symantec重金邀請(qǐng)Eugene Wang,1993年左右,Symantec推出了第一個(gè)Symantec C/C++版本,立刻便獲得了市場(chǎng)的好評(píng)。Symantec C/C++不斷完善,以最完美的、先進(jìn)的集成開發(fā)環(huán)境獲得市場(chǎng)的高度認(rèn)同。

  Watcom C/C++是以在DOS下能夠產(chǎn)生最好的最優(yōu)化程序代碼而聞名的,再加入當(dāng)時(shí)最有名的DOS Extender廠商PharLap公司也是使用Watcom C/C++,因此Watcom C/C++在專業(yè)的C/C++程序員以及系統(tǒng)程序員心中是第一品牌的C/C++開發(fā)工具。為了順應(yīng)DOS向Windows過度,也為了生存,大約也是在1993,1994年左右Watcom終于推出第一個(gè)基于Window平臺(tái)的C/C++開發(fā)工具。雖然沒有什么特色,但卻以編譯器的優(yōu)點(diǎn)成為四大C/C++開發(fā)工具之一。

  但是Symantec和Watcom由于自身的實(shí)力和發(fā)展方向,在1993年初選擇了和Microsoft簽約,使用MFC做為它們的開發(fā)工具的C/C++ Framework。而Borland選擇了堅(jiān)持開發(fā)自己的C/C++ Framework,這就是OWL。

  1994年,Microsoft為了對(duì)抗Apple和IBM OS2,推出OLE(Object Linking And Embedding)技術(shù),該技術(shù)由于可以讓W(xué)indow平臺(tái)的文件能夠內(nèi)嵌在不同的應(yīng)用程序中并且能在應(yīng)用程序中進(jìn)行編輯,因此“深入人心”。盡管該技術(shù)被后來證明是失敗的技術(shù),但卻使Microsoft取得了C/C++開發(fā)工具的勝利。

  由于OLE的復(fù)雜性使得Borland無法在OWL中實(shí)現(xiàn)此功能,因而就造成了市場(chǎng)的一些負(fù)面影響。Symantec和Watcom由于簽約的是MFC 1.x的版本,而OLE是在MFC 2.0中的技術(shù),Symantec和Watcom吃了大虧。不久以后,Symantec放棄PC的C/C++開發(fā)工具市場(chǎng),轉(zhuǎn)而開始研發(fā)Java開發(fā)工具。而Watcom則被新興而起的Sybase并購,從此消失。

  為了迎合市場(chǎng),支持OLE技術(shù),Borland在Borland C/C++ 4.5的OWL 2.5中推出OCF,但由于沒有MFC的OLE能力強(qiáng)大,也逐漸敗下陣來。雖然后來Borland繼續(xù)推出了Borland C/C++ 5.0,5.02,但終因品質(zhì)和市場(chǎng)原因而結(jié)束。

  隨后,Windows 3.0出現(xiàn)了。Windows 3.0尤其是3.1,為個(gè)人計(jì)算機(jī)引進(jìn)了真正的IDE時(shí)代。但是,Microsoft卻把精力更多地集中在C編譯器的內(nèi)部支持上,而不是把它的界面升級(jí)到一個(gè)新的時(shí)代。盡管如此,Microsoft C/C++ 7.0卻引入了對(duì)C++的支持,并引進(jìn)了Microsoft Foundation Class庫1.0版,完善了源代碼。Microsoft C/C++ 8.0成為真正的Windows IDE,這就是Visual C++ 1.0。

  Visual C++ 1.5之后,微軟決定不再將花更多的努力去支持16位編程上。雖然,Visual C++ 2.0仍提供對(duì)16位的支持,但它僅用來創(chuàng)建32位程序。

  Visual C++是沒有3.0的,版本號(hào)直接從2.0跳到4.0,以使Visual C++和MFC同步,但這種同步是短暫的,后來,Visual C++和MFC又使用了不同的版本號(hào)。

  Visual C++ 4.0引入了Internet的支持,并為Internet編程而設(shè)計(jì)的新類庫。

  Visual C++ 5.0還增加了一些新類,但主要是集中在界面的改善上,并提供一個(gè)更好的在線幫助系統(tǒng)、更高級(jí)的宏能力和對(duì)在開發(fā)者組內(nèi)進(jìn)行類和其它代碼共享的支持。5.0中還合并了Active Template Library(ATL),并顯著地改善了編譯器優(yōu)化代碼的能力。

  1998年9月,Microsoft推出了Visual C++ 6.0,它除了保留5.0對(duì)ActiveX的支持外,還支持DHTML,更新了MFC及ATL的類庫,并對(duì)模板也有擴(kuò)充,用戶可以方便地開發(fā)出類似Web瀏覽器界面的應(yīng)用程序。

  2000年7月,在PDC(Professional Developers Conference)會(huì)議上,Microsoft宣布啟動(dòng).NET方案,推出了一個(gè)全新的開發(fā)平臺(tái)Visual Studio.NET,這是Microsoft技術(shù)方向的重大轉(zhuǎn)變。在這個(gè)平臺(tái)上,包括了Visual C++、Visual Basic、Visual FoxPro和C#等開發(fā)工具。
2002年2月推出的Visual Studio.NET雖然有許多不近人意的地方,但是卻讓我們領(lǐng)略了它的強(qiáng)大之處。Visual C++ .NET除對(duì)Microsoft .NET Framework支持和界面及文檔的語言本地化這兩個(gè)最顯著特點(diǎn)外,它與Visual C++ 6.0相比,還包含其他許多新的特性,如Web應(yīng)用程序、C++托管擴(kuò)展、ATL、DCOM、MFC等方面的增強(qiáng)以及ATL Server、的支持等。

  2002年底推出Visual Studio .NET 2002,2003年4月,Visual Studio .NET 2003發(fā)布。Visual Studio .NET 2003 包含 Windows .NET Framework 的一個(gè)增強(qiáng)版本,并將移動(dòng)和嵌入式設(shè)備,如 Pocket PC 和其他采用 Microsoft Windows CE .NET 操作系統(tǒng)的設(shè)備,帶入了 .NET。

  Visual C++ .NET 2003對(duì)2002版本進(jìn)行了許多更新和優(yōu)化,除界面、庫作了改進(jìn)之外,還對(duì)在 C++托管擴(kuò)展中創(chuàng)建的Windows 窗體應(yīng)用程序提供設(shè)計(jì)器的支持以及提供對(duì)項(xiàng)目中生成自動(dòng)化模型的支持等。

  MFC和Visual C++

  Visual C++的核心是Microsoft基礎(chǔ)類庫,即通常所說的MFC。MFC相當(dāng)徹底的封裝了Win32軟件開發(fā)工具包(Software Development Kit,即通常所說的SDK)中的結(jié)構(gòu)、功能,它為編程者提供了一個(gè)應(yīng)用程序框架,這個(gè)應(yīng)用程序框架為編程者完成了很多Windows編程中的例行性工作,如管理窗口、菜單和對(duì)話框,執(zhí)行基本的輸入和輸出、使用集合類來保存數(shù)據(jù)對(duì)象等等,并且,MFC使得在程序中使用很多過去很專業(yè)、很復(fù)雜的編程課題,如ActiveX、OLE、本地?cái)?shù)據(jù)庫和開放式數(shù)據(jù)庫互聯(lián)(Open Database Connectivity,簡(jiǎn)寫為ODBC)、Windows套接字和Internet應(yīng)用程序設(shè)計(jì)等,以及其它的應(yīng)用程序界面特性,如屬性頁(也叫標(biāo)簽對(duì)話框)、打印和打印預(yù)覽、浮動(dòng)的和可定制的工具條變得更加的容易。

  早在1989年,Microsoft的程序員們開始試圖將C++和面向?qū)ο蟮木幊谈拍顟?yīng)用于Windows編程中,以編寫出一個(gè)可以使Windows編程更加簡(jiǎn)便的應(yīng)用程序框架。他們把這個(gè)應(yīng)用程序框架叫做AFX (AFX這個(gè)詞來源于Application Framework,但奇怪的是這個(gè)詞組中并沒有包含“X”這個(gè)字母)。直到今天,AFX小組早已不存在了,AFX這個(gè)名稱也于1994年初不再使用,但在Visual C++和MFC中,AFX的影子卻隨處可見,很多全局函數(shù)、結(jié)構(gòu)和宏的標(biāo)識(shí)符都被加上了AFX的前綴。

  最初的AFX版本在經(jīng)過一年的艱苦之后誕生,卻未能被大多數(shù)Windows程序員所接受。AFX的確是經(jīng)過了精心的規(guī)劃和編碼,并且,它也提供了對(duì)Windows API的高度抽象,建立了全新的面向?qū)ο蟮腁FX API,但最要命的是AFX API庫根本不兼容于現(xiàn)有的Windows API。由此導(dǎo)致的最嚴(yán)重后果是大量的SDK代碼無法移植,而程序員將學(xué)習(xí)兩種完全不同的編程方法。

  AFX不得不重新做所有的一切,他們所創(chuàng)建的新的應(yīng)用程序框架是一套擴(kuò)展的C++類,它封裝和映射了Windows API,這就是MFC的前身。過去的AFX小組也變成了MFC小組。最終,MFC的第一個(gè)公開版本于1992年3月隨Microsoft C/C++ 7.0一起推出。那時(shí)距Windows 3.1發(fā)布尚有好幾個(gè)月。在MFC 1.0中還沒有文檔/視結(jié)構(gòu),但有類CObject和CArchive。在12個(gè)月之后,MFC 2.0隨Microsoft新的編程工具Visual C++ 1.0一道出爐。與MFC 1.0一樣,MFC 2.0仍是16位的,因?yàn)?2位的Windows NT 3.1直到1993年7月才問世。在MFC 2.0中,增加了對(duì)文檔/視結(jié)構(gòu)、OLE 1.0、Windows 3.1公用對(duì)話框的支持和消息映射等。在Windows NT 3.1面世一個(gè)月以后,Microsoft推出了32版本的Visual C++和MFC 2.1,它實(shí)際上是MFC 2.0的Win32接口。

  最后一個(gè)16位的Visual C++編譯器是1993年12月推出的Visual C++ 1.5,直到今天,一些為Windows 3.1編寫16位應(yīng)用程序的程序員還在使用這個(gè)版本。1994年9月,32位的MFC 3.0伴隨著Visual C++ 2.0的一道面市,在今天的計(jì)算機(jī)圖書市場(chǎng)上,還有著大量的關(guān)于Visual C++ 2.0和MFC 3.0的圖書出售,因此,可以想象得出Visual C++ 2.0所取得的成功和它所產(chǎn)生的影響。

  但是,在Visual C++ 5.0中包括的MFC版本不是MFC 5.0,而是MFC 4.21。發(fā)展到今天,MFC已發(fā)展成一個(gè)穩(wěn)定和涵蓋極廣的C++類庫,為成千上萬的Win32程序員所使用。MFC庫是可擴(kuò)展的,它和Windows技術(shù)的最新發(fā)展到目前為止始終是同步的。并且,MFC類庫使用了標(biāo)準(zhǔn)的Windows命名約定和編碼格式,所以有經(jīng)驗(yàn)的Windows SDK程序員很容易過渡到MFC。MFC結(jié)合了Windows SDK編程概念和面向?qū)ο蟮某绦蛟O(shè)計(jì)技術(shù),從而具有極大靈活性和易用性。
]]>
編程語言之兵器譜(六)http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2445&Page=1wangxinxin2010-12-10 15:29:28微機(jī)史上最強(qiáng)的編程語言是C/C++。C最大的特色就是指針,指哪兒打哪兒,如果把指針做到應(yīng)用自如,那就是無往而不勝了, C/C++對(duì)應(yīng)兵器譜上第3位小李飛刀,刀無虛發(fā),畢竟現(xiàn)在的Web時(shí)代,后來居上的JAVA和.Net成為主流的開發(fā)語言,所以只能把它屈居第三位了。

 

但就其語言本身來看,JAVA和.Net更多的象是在C++之上減減增增。我感覺C/C++能夠稱的上編程語言史上最有影響力的語言,而它的成功完全是在其自身的優(yōu)秀特證所決定的,后面的JAVA和C#的成功是完全在C/C++的基礎(chǔ)上,它們站在了C/C++這個(gè)巨人的肩膀上。

 

C是Combined的縮寫,產(chǎn)生于1972年,C在DOS時(shí)代以其語句簡(jiǎn)潔,代碼執(zhí)行速度快,既可編寫底層代碼,又可輕松實(shí)現(xiàn)GUI的繪制,脫穎而出,成為最適合于系統(tǒng)底層程序和游戲開發(fā)的語言,被譽(yù)為中級(jí)語言,是表示它兼有高級(jí)語言和低級(jí)語言的特證。C的出現(xiàn)讓人們看到了一種新的語言風(fēng)格,感覺C語法最大的特點(diǎn)是簡(jiǎn)潔,靈活,比如分號(hào)代表語句的結(jié)束,可以讓程序的一條語句不拘于寫在一行中,這比BASIC和Fortran好,用大括號(hào)來代替Begin和End要比Pascal在書寫上省下很多。同樣一段程序,用C可以做到代碼比別的語言短,而運(yùn)行速度通常要比別的語言快。C語言中更可以調(diào)用一些DOS系統(tǒng)中斷功能,Bios中斷功能,直接訪問硬件,讀寫端口,Dos時(shí)代的C是無所不能的,比如把Dos系統(tǒng)中斷改了,讓Dos在處理例行事務(wù)時(shí),作些程序指定的操作,那是挺容易的,所以Dos下面病毒很多,不過那個(gè)時(shí)代寫底層代碼時(shí)的限制少,Windows下很多直接對(duì)硬件的訪問都限制了,Web時(shí)代更是以虛擬機(jī)和跨平臺(tái)為榮了。C/C++傾向于系統(tǒng)開發(fā),還有游戲設(shè)計(jì),只要這兩個(gè)領(lǐng)域還在,它就是永遠(yuǎn)的日不落帝國。

 

 DOS時(shí)代最流行的開發(fā)工具是Turbo C,Borland公司的優(yōu)秀產(chǎn)品,Turbo C是DOS時(shí)代C開發(fā)工具的霸主,我個(gè)人上是非常喜歡Turbo C,至今電腦上還裝著Turbo C2.0,也就2M左右,有時(shí)懷念起當(dāng)年在大學(xué)機(jī)房里用Turbo C運(yùn)行代碼的時(shí)光,還可以打開看下那熟悉的藍(lán)色界面,相信很多朋友都用過它。微軟推出的是Quick C(Windows 3.x上還有個(gè)Quick C For windows,其實(shí)也真挺好用的),但總還是比Turbo C用起來感覺差一些。從Simula,Smalltalk等面向?qū)ο蟮恼Z言的成功中吸取了經(jīng)驗(yàn),加入了面向?qū)ο蟮脑睾螅珻++面世了。

 

C++工具的早期的主流是Borland C/C++和Microsoft C/C++,在開發(fā)平臺(tái)從DOS平臺(tái)轉(zhuǎn)換到Window平臺(tái)的背景下,各大C/C++開發(fā)工具廠商紛紛推出Windows應(yīng)用的開發(fā)工具,出現(xiàn)了兩大類庫OWL和MFC,把面向?qū)ο蠹夹g(shù)在Windows應(yīng)用開發(fā)中充分利用,正是面向?qū)ο蠹夹g(shù)簡(jiǎn)化了Windows應(yīng)用的開發(fā),在Windows應(yīng)用開發(fā)過程中展現(xiàn)了面向?qū)ο蠹夹g(shù)的威力后,面向?qū)ο蠹夹g(shù)也得以更加的流行和推廣,編程領(lǐng)域進(jìn)入OO和Windows的時(shí)代。這時(shí)的開發(fā)工具更是相當(dāng)?shù)呢S富的,Borland C/C++3.0版可以開發(fā)DOS和windows兩個(gè)平臺(tái)的程序,因?yàn)槭褂肳in API寫Windows程序很麻煩,Borland推出了OWL(object windows library),用類庫封裝了windows API,與其相似的是微軟推出的MFC(Microsoft Function class)。

 

編程平臺(tái)開始向Windows平臺(tái)轉(zhuǎn)移的時(shí)候,想成為Windows平臺(tái)上C/C++開發(fā)工具的霸主的卻不只Borland和微軟兩家,李維的《Borland 傳奇》中描述了一場(chǎng)壯觀的開發(fā)工具的“圣戰(zhàn)”(也可以稱為四國大戰(zhàn)),它們是Borland C/C++, Microsoft Visual C/C++, Watcom C/C++(是否記得DOS 4GW 保護(hù)模式嗎,其實(shí)DOS時(shí)代很多游戲都是Watcom C/C++開發(fā)的,而它的運(yùn)行必須要在DOS 4GW 保護(hù)模式下,這樣解決了DOS系統(tǒng)中直接訪問的內(nèi)存不同超過1M的問題,當(dāng)年幾乎所有的DOS版的游戲都是它開發(fā)的,比如古墓麗影,仙劍奇?zhèn)b傳等), Symantec C/C++(著名的殺毒軟件諾頓的公司Symantec啊,其實(shí)它也是一家資深編程工具開發(fā)公司呢,后來的JAVA開發(fā)工具中Symantec也不甘寂寞的)四大工具閃亮登場(chǎng),而最終勝出的是Borland C++ 3.1,在Window早期,Borland C++ 3.x是最好的windows應(yīng)用的開發(fā)工具了,Borland C++ 開發(fā)出的Windows應(yīng)用是很有特色的,因?yàn)榘粹o和圖標(biāo)都有點(diǎn)和microsoft的風(fēng)格不太一樣的,當(dāng)年用Borland C++開發(fā)的應(yīng)用,現(xiàn)在一看仍能分辨出來,不過現(xiàn)在已經(jīng)難見到這種應(yīng)用程序了。Visual C++的統(tǒng)治開始了,當(dāng)微軟在這個(gè)領(lǐng)域異軍突起時(shí),Borland趕緊推出Borland C++4.0時(shí),已經(jīng)無法改變形勢(shì)了,后來的Borland C++5.0仍是優(yōu)秀的作品(記不得4.0,4.5還是5.0的Borland C++了,安裝它時(shí),屏幕上卻是開賽車時(shí)的第一視角的情景,用戶看到車內(nèi)的行程指示計(jì)指示從0%升到100%后安裝就結(jié)束了,挺有創(chuàng)意的,不過那象是一條下坡路了)。

 

Visual C++是后來的王者,現(xiàn)在能見到的Visual C++都是5.0而6.0的,喜歡Visual C++的Wizard,點(diǎn)幾下鼠標(biāo)一個(gè)Windows Application就產(chǎn)生了,Microsoft提供各種SDK,為用戶服務(wù),其中最喜歡的SDK當(dāng)然是Direct X,夢(mèng)想用C++開發(fā)個(gè)SuperMario出來,至少也要俄羅斯方塊什么的,不過入IT行業(yè)工作后,整天項(xiàng)目做的累夠嗆,沒有時(shí)間去實(shí)現(xiàn)夢(mèng)想了,入行IT后沒有機(jī)會(huì)參加C/C++項(xiàng)目,很大的遺憾了。當(dāng)年在機(jī)械行業(yè),最美好的回憶是02年為公司的閥門為一個(gè)控制系統(tǒng),兩米多高的閥門,研究生畢業(yè)的胡老師組織好硬件線路,我用一臺(tái)奔II來控制閥門的開啟和運(yùn)作,程序上由我一人開發(fā),主界面上點(diǎn)擊按鈕來讓閥門運(yùn)動(dòng)(也可在自動(dòng)模式自動(dòng)運(yùn)行),屏幕中間的最大區(qū)域是閥門當(dāng)前的狀態(tài)圖。當(dāng)系統(tǒng)接好,我第一個(gè)上來操作,一點(diǎn)鼠標(biāo)看到那么巨大的機(jī)械被我的程序控制運(yùn)作,真是很有成就感呢。我是用Win API+Direct X技術(shù)做的,DOS下全屏幕的800x600的分辨率,背景圖、按鈕、狀態(tài)圖都是我用Corel PhotoPaint , AutoCAD等工具制作的,剛啟動(dòng)時(shí)閥門的照片以一個(gè)向下縱伸展開的動(dòng)畫方式出現(xiàn)的創(chuàng)意還真有點(diǎn)意思,當(dāng)時(shí)伊拉克客戶看閥門時(shí),把我的程序(不與硬件連接的演示版)考了一份回去了,我感覺是我的程序出國了。

 

C/C++的魅力在于它的長(zhǎng)盛不衰,除了Visual C++,Borland的C++ Builder是和VB,Delphi一樣的好用的屬于C++的RAD工具,Microsoft的.Net中Visual C++.Net是其不可缺少的一部分,Linux、Unix的Shell中C Shell是重要的一個(gè),Mainframe應(yīng)用開發(fā)中C應(yīng)用廣泛。相信C/C++做為IT編程領(lǐng)域永遠(yuǎn)的傳奇會(huì)繼續(xù)展現(xiàn)它的魅力的。

 

下篇介紹當(dāng)今Web應(yīng)用開發(fā)的主流----Java。雖然JAVA最早不是為Web開發(fā)而產(chǎn)生的,但它在語言方面的特色,與Web時(shí)代的驅(qū)勢(shì)不謀而合了,于是成就了一個(gè)屬于JAVA的時(shí)代。Java對(duì)應(yīng)排行第二的上官金虹的子母龍鳳環(huán),雖說Java就一種語言,可如今的Java 1.5(tiger版),1.6(mustang版),語言上已經(jīng)和原來的Java 1.2~1.4不一樣了,它添加了對(duì)泛型,枚舉,元數(shù)據(jù)等的支持,流行很久的1.2版為基礎(chǔ)的Java2(母環(huán))和吸取了C#.Net的一些優(yōu)點(diǎn)后產(chǎn)生的Java5(子環(huán))構(gòu)成了Java的雙環(huán)。

 

]]>
Visual C++中調(diào)用匯編語言的研究與實(shí)現(xiàn)http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2444&Page=1wangxinxin2010-12-10 15:27:05摘要:本文討論了匯編語言在Visual C++中應(yīng)用的常用方法,介紹了嵌入式匯編方法的格式和模塊調(diào)用方法的協(xié)議、約定及實(shí)現(xiàn)步驟,并結(jié)合課題介紹了通過數(shù)組借助指針實(shí)現(xiàn)C++與匯編語言的混合編程的一種新的方法。
關(guān)鍵字:Visual C++;  匯編語言;  混合編程

 
1 引言
    Visual C++ 是當(dāng)今最流行的軟件開發(fā)工具之一,它可以實(shí)現(xiàn)可視化編程和支持面向?qū)ο蟮木幊碳夹g(shù)。通常在軟件開發(fā)的過程中,大部分程序采用高級(jí)語言編寫,以提高程序的開發(fā)效率,但在某些部分,例如程序的關(guān)鍵部分、運(yùn)行次數(shù)很多的部分、運(yùn)行速度要求很高的部分或直接訪問硬件的部分等利用匯編語言編寫,以提高程序的運(yùn)行效率。為了滿足兩方面的要求,人們?cè)陂_發(fā)的過程中將兩種語言進(jìn)行混合編程,這種方法使兩種語言相互調(diào)用,進(jìn)行參數(shù)傳遞,共享數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)信息,充分發(fā)揮了各種語言的特點(diǎn)和優(yōu)勢(shì),大大提高了應(yīng)用軟件的效率。因此,正確掌握Visual C++與匯編語言的接口技術(shù)對(duì)軟件開發(fā)是十分必要的。

2 Visual C++調(diào)用匯編語言的常用方法
    通常有兩種方法可以實(shí)現(xiàn)Visual C++調(diào)用匯編語言。一種方法是在從C++語言中直接使用匯編語句,即嵌入式匯編;另一種方法是用兩種語言分別編寫?yīng)毩⒌某绦蚰K,匯編語言編寫的源代碼匯編產(chǎn)生目標(biāo)代碼OBJ文件,將C++源程序和OBJ文件組建工程文件,然后進(jìn)行編譯和連接,生成可執(zhí)行文件.EXE。
2.1 VC++中嵌入?yún)R編語句的方法
    嵌入式匯編又稱行內(nèi)匯編,Visual C++提供了嵌入式匯編功能,允許在C++源程序中直接插入?yún)R編語言指令的語句,可以直接訪問C++語言程序中定義的常量、變量和函數(shù),而不用考慮二者之間的接口,從而避免了匯編語言和C++語言之間復(fù)雜的接口問題,提高了程序設(shè)計(jì)效率。
嵌入?yún)R編語言指令采用__asm關(guān)鍵字,嵌入?yún)R編格式:__asm{ 指令 },采用花括號(hào)的匯編語言程序段形式。具體應(yīng)用通常采用兩種方式,第一種方式:__asm { 匯編程序段 }, 如下所示:__asm
{
mov eax,5h
mov ecx,7h
add eax,ecx
}
另一種方式:每一條匯編語句前添加“__asm”標(biāo)記,格式:__asm 匯編語句,如下所示:
__asm mov eax,5h
__asm mov ecx,7h
__asm add eax,ecx
    在Turbo C環(huán)境中C語言程序含有嵌入式匯編語言語句時(shí),C編譯器首先將C代碼的源程序(.c)編譯成匯編語言源程序(.asm)。然后激活匯編程序Turbo Assembler將產(chǎn)生的匯編語言源文件編譯成目標(biāo)文件(.obj),最后激活Tlink將目標(biāo)文件鏈接成可執(zhí)行文件(.exe)。Visual C++ 中嵌入?yún)R編語句的編譯沒有Turbo C那樣復(fù)雜,它直接支持嵌入?yún)R編方式,不需要獨(dú)立的匯編系統(tǒng)和另外的連接步驟。因此Visual C++中嵌入?yún)R編比Turbo C中嵌入?yún)R編進(jìn)行編譯連接更為簡(jiǎn)單方便。
2.2 采用模塊調(diào)用的方法
    采用模塊調(diào)用方式,要協(xié)調(diào)命名、調(diào)用、參數(shù)傳遞和返回等進(jìn)行約定。
(1)  采用一致的調(diào)用協(xié)議
    Visual C++語言具有三種調(diào)用協(xié)議:_cdecl、_stdcall和_fastcall。MASM匯編語言利用“語言類型”確定調(diào)用協(xié)議和命名約定,支持的語言類型有:C、SYSCALL、STDCALL、PASCAL、BASIC和FORTRAN。
    Visual C++與匯編語言混合編程通常利用堆棧進(jìn)行參數(shù)傳遞,調(diào)用協(xié)議決定利用堆棧的方法和命名約定,兩者要一致,通常Visual C++采用_cdecl調(diào)用協(xié)議,MASN匯編語言采用C語言調(diào)用協(xié)議。
(2)  入口參數(shù)和返回參數(shù)的約定
    不論何種整數(shù)類型進(jìn)行參數(shù)傳遞時(shí)都擴(kuò)展成32位,Visual C++中沒有遠(yuǎn)、近調(diào)用之分,所有調(diào)用都是32位的偏移地址,所有的地址參數(shù)也都是32位偏移地址,在堆棧中占4個(gè)字節(jié)。圖1給出了采用C++語言調(diào)用協(xié)議的堆棧示意圖。參數(shù)返回時(shí),對(duì)于小于等于32位的數(shù)據(jù)擴(kuò)展為32位,存放在EAX寄存器中返回;4-8個(gè)字節(jié)的返回值存放在EDX、.EAX寄存器中返回;更大字節(jié)數(shù)據(jù)則將它們的地址指針存放在EAX中返回。

圖片點(diǎn)擊可在新窗口打開查看

    (3)  聲明公用函數(shù)名和變量名
    對(duì)Visual C++和匯編語言使用的公用函數(shù)和變量應(yīng)該進(jìn)行聲明,并且標(biāo)識(shí)符應(yīng)該一致,C++語言對(duì)標(biāo)識(shí)符區(qū)分字母的大小寫,而匯編不區(qū)分大小寫。在Visual C++語言程序中,采用extern “C”{  }對(duì)所調(diào)用的函數(shù)和變量給予說明。說明形式如下:
    對(duì)函數(shù)的說明:extern “C” { 返回值類型 調(diào)用協(xié)議 函數(shù)名稱(參數(shù)類型表);}
    對(duì)變量的說明:extern “C” { 變量類型 變量名;}
    匯編語言程序中供外部使用的標(biāo)識(shí)符應(yīng)該標(biāo)識(shí)PUBLIC屬性,使用外部標(biāo)識(shí)符應(yīng)該用extern說明。
 2.3 模塊調(diào)用混合編程的實(shí)現(xiàn)步驟
    采用模塊調(diào)用方式進(jìn)行混合編程一般執(zhí)行的步驟如下:(1)建立C++源程序(.cpp);(2)建立匯編語言源程序,并把匯編語言匯編成.obj文件;(3)建立工程文件.prj,將C++源程序和.obj文件放入該工程項(xiàng)目;(4)對(duì)工程文件進(jìn)行編譯、連接,生成可執(zhí)行文件.exe。
    在與Visual C++混合編程的匯編語言過程中,編程環(huán)境是32位的,應(yīng)該注意與16位MS-DOS環(huán)境的區(qū)別,在這種環(huán)境下的寄存器是32位的,因此匯編語言過程存取堆棧應(yīng)該使用32位寄存器EBP進(jìn)行相對(duì)尋址,而不是采用BP。匯編語言簡(jiǎn)化段定義的格式應(yīng)該采用flat模式,并且匯編時(shí)采用選項(xiàng)/coff,ML命令的選項(xiàng)/coff使得產(chǎn)生的.obj文件采用32位的格式。
3 在Visual C++中調(diào)用匯編語言的第三種方法
    通常以上兩種方法就能夠?qū)崿F(xiàn)C++與匯編語言混合編程,但是在一些特殊的情況下,用這兩種方法卻不能滿足功能的需要,我們提出了一種新的方法實(shí)現(xiàn)二者的混合編程:通過數(shù)組借助指針實(shí)現(xiàn)二者的混合編程。下面結(jié)合我們開發(fā)的課題――數(shù)控系統(tǒng)邏輯控制系統(tǒng)軟件開發(fā),來進(jìn)行具體說明。
    該課題在Visual C++ 6.0的環(huán)境下進(jìn)行開發(fā)的,上層采用C++語言,最底層采用了匯編語言,在C++語言中要調(diào)用匯編語言的編譯的結(jié)果,并進(jìn)行回填,如果用通用的混合編程方法無法實(shí)現(xiàn)二者的調(diào)用,因?yàn)榈讓訁R編語言是把所有的邏輯運(yùn)算功能指令匯編在一起,而在C++語言中根據(jù)需要在需要的地方調(diào)用匯編語言中的某一功能模塊,因此對(duì)匯編語言編譯后的.OBJ文件無法進(jìn)行控制。具體實(shí)現(xiàn)方法如下:
    (1)把包括所有的邏輯指令的匯編語句編成一個(gè)匯編模塊程序,在匯編編譯器(如masm 6.x)中將匯編程序編譯成.OBJ文件。
    (2)將匯編生成的機(jī)代碼放在一個(gè)數(shù)組中,
例如定義一個(gè)數(shù)組變量unsigned char OBJMOD[1241]。
     (3)定義多個(gè)指針類型變量指向OBJMOD數(shù)組元素的地址,該地址對(duì)應(yīng)每個(gè)匯編功能模塊的首地址,如定義一個(gè)指針變量unsigned char *LIBC21=&OBJMOD[869]。
     (4)通過函數(shù)COPILE(*pModal)模塊,例如編譯匯編LIBC21功能模塊時(shí),通過調(diào)用COPILE(LIBC21) 函數(shù),把匯編編譯生成的機(jī)代碼分別傳遞到工作區(qū)域WKAREA中,通過WKAREA[POSIRR]=BUFRIS[PTRIS]來實(shí)現(xiàn)二次填充,把匯編機(jī)代碼中改寫的內(nèi)容改寫成需要的地址或值,最后通過調(diào)用一系列函數(shù),把結(jié)果保存到文件中。
     本課題采用這種方法實(shí)現(xiàn)了C++和匯編語言的混合編程,從而實(shí)現(xiàn)C++語言與匯編語言的無縫結(jié)合。
4 結(jié)束語
    Visual C++和匯編語言混合編程可以實(shí)現(xiàn)優(yōu)勢(shì)互補(bǔ),尤其用在高級(jí)語言開發(fā)底層軟件方面,例如用Visual C++6.0環(huán)境開發(fā)數(shù)控軟件PLC的控制功能,這種優(yōu)勢(shì)更為明顯,具有很好的實(shí)際應(yīng)用價(jià)值。

]]>
從VC++6.0不足看Visual C++2010新特性http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2443&Page=1wangxinxin2010-12-10 15:25:38  VC++ 6.0的問題

  VC++ 6.0是Visual Studio 6.0中的一種重要編程語言,也是中國C++開發(fā)人員使用最多的開發(fā)工具之一。 Visual C++是構(gòu)建Windows平臺(tái)下應(yīng)用程序功能最強(qiáng)大而又最復(fù)雜的工具,是目前世界上使用最多的開發(fā)工具之一,應(yīng)用極度廣泛,從桌面應(yīng)用程序到服務(wù)器程序,從系統(tǒng)軟件到應(yīng)用軟件,圖形圖像,語音技術(shù),設(shè)備驅(qū)動(dòng),網(wǎng)絡(luò)安全,加密解密等等幾乎無處不在。主流的3 種操作系統(tǒng)Windows,Linux,Unix內(nèi)核都是用C語言和匯編語言寫的,而上層的高級(jí)特性都是用C++編寫。

  直到今天,Visual C++6.0仍然占據(jù)著C++開發(fā)工具的絕對(duì)優(yōu)勢(shì)的地位。自從微軟從2000年開始推行.NET戰(zhàn)略以來,其核心的編程語言是C#,從那個(gè)時(shí)候,C++的支持力度就開始不斷的下滑,雖然Visual C++也有幾次更新,但都不是很令人滿意,更靈人焦慮的是,有些開發(fā)者開始懷疑Visual C++的前途。盡管Visual C++的一些快捷開發(fā)被其他開發(fā)語言所取代,由于C++可以與操作系統(tǒng)的天生的曖昧關(guān)系,能夠與C語言無縫結(jié)合,所以Visual C++不可能被淘汰,尤其是對(duì)于底層開發(fā)。盡管Visual C++ 6.0很強(qiáng)大,是編程語言里一再受寵的幸運(yùn)兒。但是Visual C++6.0已經(jīng)成了昨日黃花,尤其讓所有Visual C++6.0開發(fā)人員郁悶的是Visual C++6.0開發(fā)的界面還停留在早期的水平上,界面粗糙,操作復(fù)雜,比起現(xiàn)在華麗而又奪人眼目的界面設(shè)計(jì),更是遜色不少。而且Visual C++6.0也不完全符合C++標(biāo)準(zhǔn)。

  正是由于Visual C++6.0的界面設(shè)計(jì)還停留在Windows 98時(shí)期的水平,操作復(fù)雜,再加上它不是完全符合C++標(biāo)準(zhǔn),在代碼和BUG跟蹤調(diào)試上異常復(fù)雜,這也提高了踏入VC++開發(fā)的門欖。但是隨著Visual C++2010的推出,全面支持最新的C++標(biāo)準(zhǔn)、改善了IDE的效率,并且引入了很多新的特性,這些功能的增強(qiáng),大大提高程序員們的開發(fā)效率,帶來更高的代碼生產(chǎn)力與開發(fā)的便捷。

  Visual C++2010 新特性

  Visual C++2010為所有的VC++開發(fā)人員做了貼心而又周全的考慮,下面我們從可視化設(shè)計(jì)、人性化使用、安全可靠、支持C++新標(biāo)準(zhǔn)和部署簡(jiǎn)潔等方面介紹Visual C++2010的新特性。

  (1)Ribbion界面設(shè)計(jì)可視化

  在Visual C++6.0開發(fā)里面,界面簡(jiǎn)單丑陋是其中一個(gè)不爽的地方。盡管在Visual C++ 2008里面對(duì)Ribbion功能有所改善,但是仍不能進(jìn)行可視化設(shè)計(jì),Visual C++ 2010新增了Windows7的風(fēng)格,同時(shí)最大的革新就是實(shí)現(xiàn)了可視化設(shè)計(jì),很容易設(shè)計(jì)出漂亮的程序界面。 下面我們體驗(yàn)一下Visual C++ 2010界面可視化設(shè)計(jì)的特性。具體操作步驟如下:

  1. 打開Microsoft Visual Studio 2010,點(diǎn)擊“文件->新建->項(xiàng)目”,打開“新建項(xiàng)目”窗體

  2. 在“新建項(xiàng)目”窗體中,選擇“Visual C++”節(jié)點(diǎn)中的“CLR”,然后在“模板”窗格中選擇“Windows 窗體應(yīng)用程序”。名稱輸入“WinFormDemo”。

圖片點(diǎn)擊可在新窗口打開查看
 

  3. 隨即打開Windows 窗體設(shè)計(jì)器,出現(xiàn)Form1 窗體

圖片點(diǎn)擊可在新窗口打開查看
 

  4.設(shè)置窗體屬性,Text為WinFormDemo;添加一個(gè)Label,一個(gè)Button,一個(gè)DateTimePicker,具體如下:

控件類型 控件名稱 Text屬性
Label labMessage 請(qǐng)選擇日期
Button dtpSelected  
DateTimePicker btnExit 退出

圖片點(diǎn)擊可在新窗口打開查看

]]>
Windows CE 開發(fā)語言Visual C++http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2442&Page=1wangxinxin2010-12-10 15:17:26

 對(duì)話框

  現(xiàn)在我們使用進(jìn)度控件來創(chuàng)建一個(gè)對(duì)話框。我們首先添加一個(gè)菜單項(xiàng)和一個(gè)消息句柄來調(diào)用該對(duì)話框。以下是詳細(xì)的操作步驟:

  1. 在 IDR_MAINFRAME 菜單資源中添加一個(gè)新的彈出菜單,并命名為 Tools;

  2. 在 Tools 彈出菜單中添加一個(gè)菜單項(xiàng),命名為 Run WCE First Dialog;

  3. 使用 ClassWizard 給新創(chuàng)建的 Run WCE First Dialog 菜單項(xiàng)添加一個(gè)命令句柄;

  下面我們來添加一個(gè)對(duì)話框,將控件放入其中,并綁定該對(duì)話框到一個(gè)類。

  4. 插入一個(gè)新的對(duì)話框資源,并設(shè)置其標(biāo)題為 WCE First Dialog,資源標(biāo)號(hào)為 IDD_FIRST_DLG;

  5. 將 Ok 按鈕的標(biāo)題(caption)改為 Close;

  6. 將 Cancel 按鈕的標(biāo)題改為 Start,并將其資源標(biāo)號(hào)改為 IDB_START_BTN;

  7. 從控件面板上拉下一個(gè)進(jìn)度控件并放置到對(duì)話框中。不要修改該進(jìn)度控件的風(fēng)格(styles)、標(biāo)題(caption)和資源標(biāo)號(hào)(resource ids);

  8. 根據(jù)掌上電腦的屏幕面積調(diào)整該對(duì)話框的大小,使之能在掌上電腦中正確顯示。建議可以設(shè)為 196 x 47 象素大小;

  9. 使用 ClassWizard 綁定該對(duì)話框資源到一個(gè)新的類:CWCEFirstDialog;

  10. 創(chuàng)建完對(duì)話框類后,再使用 ClassWizard 來給進(jìn)度控件添加一個(gè)成員變量,叫做 m_progressCtrl;

  11. 為 Start 按鈕添加一個(gè)命令按鈕句柄;

  現(xiàn)在你已經(jīng)將所有的預(yù)備設(shè)置都添加到程序中去了。雖然我們所使用的進(jìn)度顯示控件和對(duì)話框并沒有什么實(shí)際意義,但也能夠滿足我們的這個(gè)短小的入門教程的要求了。當(dāng)我們選中 Run WCE First Dialog 菜單項(xiàng)時(shí),對(duì)話框?qū)@示出來;然后點(diǎn)擊 Start 按鈕,進(jìn)度控件就會(huì)從0增長(zhǎng)到30000,最后顯示一個(gè)標(biāo)準(zhǔn)的 Windows 消息框;點(diǎn)擊 Close 按鈕將關(guān)閉該對(duì)話框。

  為了設(shè)置進(jìn)度指示器,你必須在對(duì)話框的 WM_INITDIALOG 消息句柄中設(shè)置進(jìn)度值范圍和步長(zhǎng)。首先使用 ClassWizard 為 Windows 消息 WM_INITDIALOG 添加一個(gè)消息句柄。在 OnInitDialog() 函數(shù)中添加下列代碼來設(shè)置進(jìn)度指示器的范圍和步長(zhǎng):

BOOL CWCEFirstDialog::OnInitDialog()
{
CDialog::OnInitDialog();

m_progressCtrl.SetRange(0,30000);
m_progressCtrl.SetStep(1);

return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}


  下一步,當(dāng)用戶點(diǎn)擊 Start 按鈕時(shí),進(jìn)度控件的值要開始增長(zhǎng)。在增長(zhǎng)結(jié)束時(shí),還要顯示一個(gè)消息框。下列代碼完成上述任務(wù):

void CWCEFirstDialog::OnStartBtn()
{
for(int i = 0; i <=30000; i++)
{
m_progressCtrl.StepIt();
}

AfxMessageBox(_T("Progress Complete!!!"), MB_OK);
}


  完成以上代碼后,你就可以運(yùn)行你的程序看看效果了。

]]>
C和C++語言學(xué)習(xí)總結(jié)http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2441&Page=1wangxinxin2010-12-10 15:15:351、if,for,switch,goto
2、#define,const
3、文件拷貝的代碼,動(dòng)態(tài)生成內(nèi)存,復(fù)合表達(dá)式,strcpy,memcpy,sizeof
4、函數(shù)參數(shù)傳遞,內(nèi)存分配方式,內(nèi)存錯(cuò)誤表現(xiàn),malloc與new區(qū)別
5、類重載、隱藏與覆蓋區(qū)別,extern問題,函數(shù)參數(shù)的缺省值問題,宏代碼與內(nèi)聯(lián)函數(shù)區(qū)別
6、構(gòu)造和析構(gòu)的次序,String函數(shù)定義


具體實(shí)現(xiàn):
1、if,for,switch,goto
if:
bool int float pointer char 變量的使用方法
bool  bParam;
int  iParam;
float fParam;
int*  pParam;
char  cParam;
if(bParam) ,if(!bParam);
if(iParam == 0 ),if(iParam != 0 );
if(fParam>= -0.00001 && fParam <= 0.00001);
if(pParam == NULL),if(pParam != NULL);
if(cParam == '\0'),if(cParam != '\0');

if/else/return 的使用方法
if(condition)    可以等價(jià)為  return (condition?x:y);
{
  return x;
}
else
{
  return y;
}

for:
執(zhí)行效率問題:
int row,col,sum;
int a[100][5];
for(row=0;row <100;row++)      效率低于    for(col=0;col <5;col++)
{                                        {
  for(col=0;col <5;col++)                    for(row=0;row <100;row++)
  {                                          {
      sum = sum+a[row][col];                    sum = sum+a[row][col];
  }                                          }
}                                        }

int i;
for(i=0;i <N;i++)            效率低于    if(condition)
{                                        {
    if(condition)                            for(i=0;i <N;i++) 
      DoSomething();                            DoSomething();
    else                                  }
      DoOtherthing();                    else
}                                        {
                                            for(i=0;i <N;i++) 
                                                DoOtherthing();
                                          }

for (int x=0;x <=N-1;x++)  直觀性差于    for (int x=0;x <N;x++)

switch:
switch(variable)
{
    case value1: ...
                break;
    case value2: ...
                break;
    default:    ...
                break;
}
switch(c)中的c的數(shù)據(jù)類型可以是int,char,long,unsigned int,bool.
variable必須是整數(shù)或者強(qiáng)制為整數(shù),由于char實(shí)際上是ASCII碼,所以也可以.
c不可以是double,float,char*.

goto:
goto主要用于
{...
  {...
      {....
        goto error;
      }
  }
}

error:
    ...


2、#define,const
#define和const區(qū)別
1、#define C語言
  const  C語言 C++語言
  const常量有數(shù)據(jù)類型,編譯器會(huì)進(jìn)行類型安全檢查,而#define沒有數(shù)據(jù)類型,
  const的常量可以進(jìn)行調(diào)試,但宏常量不能進(jìn)行調(diào)試.
2、const的使用方法
在全局定義 const float PI=3.1415926
在類中定義
class A
{...
    A(int size);
    const int SIZE;
};
A::A(int size):SIZE(size)
{
  ...
}
對(duì)參數(shù)和函數(shù)的定義(const只能修飾輸入?yún)?shù),不能修飾輸出參數(shù))
const int x=1;  表示x的值是1,在程序中不能改變;
const int* x;  表示x代表的地址所指向的內(nèi)容是不能改變得;
int const* x;  與const int* x;的表示的意思一樣;
int * const x;  表示x代表的地址是不能改變的;

當(dāng)是輸入?yún)?shù)時(shí),不需要是void Func(const int i),void Func(const int& i),可以是void Func(int i)
因?yàn)檩斎雲(yún)?shù)采用"值傳遞"(const int i),由于函數(shù)將自動(dòng)產(chǎn)生臨時(shí)變量用于復(fù)制該參數(shù),該輸入?yún)?shù)本來就無需保護(hù),所以不要加const修飾;
不用const int& i的原因在于內(nèi)部數(shù)據(jù)類型的參數(shù)不存在構(gòu)造、析構(gòu)的過程,而復(fù)制也非常快,"值傳遞"和"引用傳遞"的效率幾乎相當(dāng).

當(dāng)是輸入?yún)?shù)時(shí),不需要是void Func(const A a),void Func(A a),可以是void Func(A& a)或void Func(const A& a)
不用const A a,A a的原因是函數(shù)的效率比較低,因?yàn)楹瘮?shù)體內(nèi)將產(chǎn)生A類型的臨時(shí)對(duì)象用于復(fù)制參數(shù)a,而臨時(shí)對(duì)象的構(gòu)造、復(fù)制和析構(gòu)過程都需要消耗時(shí)間
最好用const A&a的原因是A&a中的a可以被改變,A&a和const A&a的好處在于都不會(huì)產(chǎn)生臨時(shí)對(duì)象,效率高;

const A Func(const A&a )const的好處
第一個(gè)const表示返回的是個(gè)內(nèi)部產(chǎn)生的對(duì)象,它不能被修改
const A Func(...)
{...}
const A a=Func(...);//不能是A a=Func(...);
第二個(gè)const表示輸入的參數(shù)是引用傳遞,函數(shù)內(nèi)部不會(huì)產(chǎn)生臨時(shí)對(duì)象,而且這個(gè)對(duì)象不能被內(nèi)部修改
第三個(gè)const表示此函數(shù)內(nèi)部的所涉及的數(shù)據(jù)成員不能修改
class Stack
{
  int m_num;
  int GetCount(void) const;
  int Pop(void);
}
int Stack::GetCount(void) const
{
  m_num++;//編譯錯(cuò)誤,企圖修改數(shù)據(jù)成員m_num;
  Pop();//編譯錯(cuò)誤,企圖調(diào)用非const函數(shù)
}

3、文件拷貝的代碼
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("Hello World!\n");
FILE* in;
FILE* out;
in=fopen("d:\\1.txt","rb");
out=fopen("d:\\2.txt","wb");
char ch=fgetc(in);
while(!feof(in))
{
  fputc(ch,out);
  ch=fgetc(in);
}
fclose(in);
fclose(out);
return 0;
}

動(dòng)態(tài)生成內(nèi)存的代碼
------------------------------------------
正確代碼:
void GetMemory(char **p, int num)
{
  *p = (char *)malloc(sizeof(char) * num);
}
char* GetMemory2(int num)
{
  char* p = (char *)malloc(sizeof(char) * num);
  return p;
}
------------------------------------------
錯(cuò)誤的代碼:
void GetMemory3(char *p, int num)
{
  p = (char *)malloc(sizeof(char) * num);
}

------------------------------------------
void Test(void)
{
  char *str = NULL;
  GetMemory(&str, 100); // 注意參數(shù)是&str,而不是str
  strcpy(str, "hello");
  cout < < str < < endl;
  free(str);

  str=NULL;
  str=GetMemory2(100);
  strcpy(str, "hello");
  cout < < str < < endl;
  free(str);

  str=NULL;
  GetMemory3(str, 100); // str 仍然為NULL
  strcpy(str, "hello"); // 運(yùn)行錯(cuò)誤
  cout < < str < < endl;//運(yùn)行錯(cuò)誤
  free(str);//運(yùn)行錯(cuò)誤
}

strcpy代碼
char* strcpy(char* strDest,const char* strSrc)
{
    if(strDest==NULL||strSrc==NULL) return NULL;
    char* pStr=strDest;
    while((*strDest++=*strSrc++)!='\0)
          NULL;
    return pStr; 
}

復(fù)合表達(dá)式
d = (a = b + c) + r ;
該表達(dá)式既求a 值又求d 值.應(yīng)該拆分為兩個(gè)獨(dú)立的語句:
a = b + c;
d = a + r;

if (a < b < c) // a < b < c 是數(shù)學(xué)表達(dá)式而不是程序表達(dá)式
并不表示
if ((a <b) && (b <c))
而是成了令人費(fèi)解的
if ( (a <b) <c )


memcpy代碼
void* memcpy(char* strDest,const char* strSrc,size_t size)
{
    if(strDest==NULL||strSrc==NULL) return NULL;
    if(size <=0) return NULL;   
    char* pStr=strDest;
    while(size-->0)
        *strDest++=*strSrc++;
    return pStr;   
}

sizeof:
i.在32位操作系統(tǒng)中,基本數(shù)據(jù)類型
類型                  字節(jié)長(zhǎng)度
char                    1
short                    2
short    int            2
signed short            2
unsigned short          2
int                      4
long    int            4
signed  int            4
unsigned int(unsigned)  4
long                    4
unsigned long            4
float                    4
double                  8
void*                    4 (所有指針類型長(zhǎng)度都一樣)(char*,int*,float*,double*)
enum                    4

ii.在32位操作系統(tǒng)中,定義或函數(shù)中的大小
char a[]="hello";
char b[100];
char *p=a;
類型                  字節(jié)長(zhǎng)度
sizeof(a)                6
sizeof(b)                100
sizeof(p)                4

void Func(char a[100])
{
    sizeof(a);        //4
}

#pragma pack(1)
struct A
{
    int i;
    char j;
};
sizeof(A)              //5

#pragma pack(1)
struct A
{
int o;
int j;
union
{
int i[10],j,k;
};

};
sizeof(A)              //48

#pragma pack(1)
struct A
{
    enum  day{monring,  moon,  aftermoon}; 
};
sizeof(A)              //1
sizeof(A::day)        //4
]]>
C++與Java語言及其開發(fā)工具 (2)http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2440&Page=1wangxinxin2010-12-10 15:13:24在Java中,對(duì)變量和方法的訪問控制是通過訪問修飾符來實(shí)現(xiàn)的。Java定義了4種
訪問級(jí)別:公共(public)、受保護(hù)(protected)、私有(private)和友好(friendly)。
公共類型的方法及變量可從任意類進(jìn)行訪問;受保護(hù)類型的方法及變量只能從當(dāng)前
類及其子類訪問;私有類型的方法及變量則只能從當(dāng)前類訪問。如果未給出這三種
類型中任意一種的顯式說明 ,表明相應(yīng)的方法或變量屬于"友好"類型,從而可由屬
于同一"包"(package)內(nèi)的所有類進(jìn)行訪問。在Java內(nèi),"包"是一個(gè)單獨(dú)的編譯單
位,它是具有某種共性的類所組成的集合。通過定義包這個(gè)單位,可實(shí)現(xiàn)相關(guān)對(duì)象
之間的相互訪問,同時(shí)把這些對(duì)象與包之外的其它對(duì)象隔離。 

面向?qū)ο蟮木幊虣C(jī)制是Java的一個(gè)極為重要的方面。在Java內(nèi),如果不創(chuàng)建新類,
就無法創(chuàng)建應(yīng)用程序。Java定義了一個(gè)特殊的超類Object,用戶創(chuàng)建的類都是Object
的子類。J ava程序既可在解釋器內(nèi)也可在瀏覽器內(nèi)運(yùn)行,但無論采用哪種方式,都
必須先創(chuàng)建一個(gè)類實(shí)例,然后才能提交運(yùn)行。此外,利用繼承機(jī)制,用戶還可充分利
用各種超類提供的功能。 

2. 與C++的差別 

盡管C++程序員可以相對(duì)容易地掌握J(rèn)ava編程,但他們?nèi)匀槐仨毧朔䦶腃++帶來的一
些舊習(xí)慣。Java取消了C++中的如下特性或功能: 

·結(jié)構(gòu)或指針 ·#define語句 

·指針 ·多重繼承 

·獨(dú)立的函數(shù) ·GOTO語句 

·操作符重載 ·自動(dòng)類型轉(zhuǎn)換 

Java不支持結(jié)構(gòu)和指針,而且取消了C++中的#define或#typedef語句和頭文件。 

事實(shí)上,constant和typedef這兩條語句包含了#define語句的作用。現(xiàn)在,結(jié)構(gòu)和
聯(lián)合已經(jīng)被Java的類所代替。刪除這些特性的原因是:由于其希望維持與C語言的
向后兼容性,C ++的語言規(guī)范包含了大量冗余。比如,類實(shí)際上就已經(jīng)包括了結(jié)構(gòu)
和聯(lián)合的作用,因此這兩種數(shù)據(jù)結(jié)構(gòu)完全可以取消。關(guān)于#define語句,Java語言規(guī)
范的制訂者認(rèn)為:盡管該語句的出發(fā)點(diǎn)是為了增強(qiáng)程序的可讀性,但實(shí)際效果卻恰
恰相反,它常常導(dǎo)致難讀的代碼,故應(yīng)該予以取消。Java不再支持獨(dú)立函數(shù),因此任
何函數(shù)都必須封裝到某個(gè)類中。由于人們普遍認(rèn)為, C++所用的超類是非常不穩(wěn)定
的,因此Java拋棄了C++中的多繼承并代之以接口。Java的接口指的是,在別的類看
來一個(gè)類所能實(shí)現(xiàn)的方法。它所顯示的只是一個(gè)類的方法或常量和變量 ,而不是
這個(gè)類的全部結(jié)構(gòu)。 

最后,Java還取消了C++中的GOTO語句、操作符重載、自動(dòng)類型轉(zhuǎn)換及指針數(shù)據(jù)類
型。 GOTO語句引起的爭(zhēng)議已經(jīng)有很多年了,可一直陰魂不散,這跟某些程序員對(duì)該
語句一直情有獨(dú)鐘有關(guān)。C++仍然支持?jǐn)?shù)據(jù)類型的自動(dòng)轉(zhuǎn)換,但Java要求編程人員
顯式實(shí)現(xiàn)數(shù)據(jù)類型之間的轉(zhuǎn)換。自動(dòng)數(shù)據(jù)類型轉(zhuǎn)換使得兩個(gè)數(shù)據(jù)類型互不兼容的
變量可以相互賦值,而不需要給出顯式說明。這有時(shí)會(huì)導(dǎo)致一些問題,其中最常見
的是精確度損失。比方說,如果把一個(gè)帶符號(hào)的32位整數(shù)賦給一個(gè)無符號(hào)整數(shù),則
所有的結(jié)果均為正數(shù)。Java的設(shè)計(jì)者們認(rèn)為這很容易引起程序錯(cuò)誤,從而決定不支
持這種轉(zhuǎn)換方式。 

某些C和C++程序員也許會(huì)覺得遺憾,因?yàn)镴ava不再支持他們非常愿意使用的指針類
型。但我們都知道,指針是調(diào)試程序時(shí)使人最感頭痛的地方之一。Java的設(shè)計(jì)者們
認(rèn)為,由于Ja va取消結(jié)構(gòu)類型并且把數(shù)組封裝到了對(duì)象里面,指針已經(jīng)不再有用武
之地。但有些C和C++高級(jí)編程人員可能仍然需要一段時(shí)間才能走出指針的陰影。
因?yàn)橹羔樀挠梅ūM管很難掌握,可一旦掌握了其使用技巧,就會(huì)讓人感到它的功能
的確非常強(qiáng)大。作為一種面向分布式計(jì)算環(huán)境的編程語言,Java放棄對(duì)指針的支持
是非常順理成章的,因?yàn)橹挥羞@樣,才可能產(chǎn)生一種穩(wěn)可能產(chǎn)生一種穩(wěn)定、高效而
且安全的代碼。 

3. 內(nèi)存管理和線索 

Java語言帶來的好處還在于其自動(dòng)內(nèi)存管理和線索控制。在C和C++中,內(nèi)存必須用
free、 malloc和其它許多內(nèi)存管理標(biāo)準(zhǔn)庫管理。因此,系統(tǒng)要了解何時(shí)分配、釋
放內(nèi)存并且跟蹤所有的內(nèi)存使用情況是非常困難的。如果要在C和C++中實(shí)現(xiàn)線索
功能,必須使用一個(gè)可對(duì)線索進(jìn)行各種控制的類庫。而在Java中,盡管線索仍然需
要類的支持,但系統(tǒng)卻在語言級(jí)包括了線索同步機(jī)制。 

Java具有內(nèi)嵌的內(nèi)存管理程序。一旦創(chuàng)建了一個(gè)對(duì)象,Java的運(yùn)行系統(tǒng)就開始跟蹤
這個(gè)對(duì)象,直到不再需要跟蹤該對(duì)象的所有引用為止。當(dāng)某個(gè)對(duì)象不存在相應(yīng)的引
用時(shí),Java把這個(gè)對(duì)象放到一個(gè)用于垃圾搜集的棧內(nèi)。為在性能損失最小的情況下
提供自動(dòng)垃圾搜集機(jī)制,這個(gè)垃圾搜集程序?qū)⒃诤笈_(tái)或作為低優(yōu)先級(jí)線索運(yùn)行。這
樣,Java的垃圾搜集軟件將在前臺(tái)線索的執(zhí)行期間抽空?qǐng)?zhí)行,或者在系統(tǒng)顯式提出
需要使用那些被已經(jīng)死亡的類所占用的內(nèi)存空間時(shí)執(zhí)行。 

從后臺(tái)內(nèi)存管理程序可以很明顯地看出,多線索的確可以增強(qiáng)Java環(huán)境的相對(duì)性能。
鑒于多線索的重要性,Java在語言級(jí)提供了線索同步機(jī)制,使多線索成為一種內(nèi)嵌
特性。Java 語言支持針對(duì)方法的同步修飾符,并通過該修飾符來指明線索的運(yùn)行
順序。此外,Java還能控制方法與實(shí)例變量的相互作用機(jī)制,確保了各方法之間在
修改數(shù)據(jù)時(shí)不會(huì)產(chǎn)生沖突。 

Java的內(nèi)存管理和線索支持還具有使Java語言簡(jiǎn)單化的作用。正是由于把內(nèi)存管
理任務(wù)嵌入到了Java環(huán)境,Java語言才可以取消指針數(shù)據(jù)類型、malloc和free函
數(shù)。這樣,程序員就可以把更多的時(shí)間化在真正的編程工作上,而不是去跟蹤調(diào)試
與內(nèi)存使用相關(guān)的程序錯(cuò)誤。正是由于其多線索機(jī)制,Java才可以為一個(gè)可移植
的解釋系統(tǒng)提供較高的性能。 

Java語言非常適合于異構(gòu)網(wǎng)絡(luò)系統(tǒng)(尤其是Internet)上的高性能、分布式計(jì)算環(huán)
境。雖然個(gè)人機(jī)系統(tǒng)未必可以看作是高性能的,但目前的個(gè)人機(jī)已經(jīng)具有相當(dāng)好
的性能。再者, 目前幾乎所有操作系統(tǒng)均提供了各種高級(jí)特性,如內(nèi)嵌的聯(lián)網(wǎng)功
能和真正的多任務(wù)、多線索支持等。然而在幾年前,這些功能還只有昂貴的UNIX
工作站才能提供。有了這些軟硬件基礎(chǔ) ,加上Java的簡(jiǎn)單易學(xué)及面向?qū)ο筇匦?
未來的程序員將可以在聯(lián)入網(wǎng)絡(luò)的個(gè)人機(jī)上開發(fā)適合于在各種硬件和軟件平臺(tái)上
發(fā)布的高級(jí)"內(nèi)容"。

]]>
C++領(lǐng)域天才 D語言領(lǐng)袖將到中國傳道http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2439&Page=1wangxinxin2010-12-10 15:12:18軟件開發(fā)2.0”大會(huì)組委會(huì)了解到,被Scott Mayer列入五位最重要的C++開發(fā)人員之列,公認(rèn)為C++領(lǐng)域最頂尖的一位天才人物Andrie Alexandrescu將親臨北京,并在這次大會(huì)上做精彩演講。
圖片點(diǎn)擊可在新窗口打開查看
Andrei Alexandrescu被認(rèn)為新一代C++天才的代表人物,2001 年,Andrei撰寫了開風(fēng)氣之先的經(jīng)典名著《Modern C++ Design》,由于其中對(duì)Template技術(shù)的精湛運(yùn)用,該書震撼了整個(gè)C++社群,開辟了C++編程領(lǐng)域的“Modern C++”新時(shí)代。

2005年,Andrei與C++標(biāo)準(zhǔn)委員會(huì)主席Herb Sutter合作的是《C++ Coding Standard》則回歸樸實(shí),將C++社群二十多年積累的寶貴智慧匯集與一本薄薄的小書之中。之后,Andrei陸續(xù)發(fā)表了多篇思想深邃、技術(shù)精湛的文章,更開發(fā)了若干富于高度技巧性的軟件和程序庫,得到了整個(gè)C++社群的廣泛尊重。

Andrei Alexandrescu在軟件開發(fā)2.0大會(huì)上將有兩場(chǎng)重要的講座。

其中一場(chǎng)將講述融合了C語言的強(qiáng)大威力,以及Python和Ruby的開發(fā)效率的D 語言。D語言所具有的集廢料收集、手工內(nèi)存操作、契約式設(shè)計(jì)、高級(jí)模板技術(shù)、內(nèi)嵌匯編、內(nèi)置正則表達(dá)式、內(nèi)置單元測(cè)試、Mixin風(fēng)格多繼承、類 Java包管理機(jī)制、 內(nèi)置同步機(jī)制、內(nèi)建運(yùn)行時(shí)信息等特性被認(rèn)為將改變軟件開發(fā)的未來。D語言由著名的語言設(shè)計(jì)和實(shí)現(xiàn)專家Walter Bright創(chuàng)造,歷經(jīng)最初的懷疑與不屑,逐漸成為令整個(gè)系統(tǒng)開發(fā)者社群矚目的明日之星。而以C ++聞名于世的Andrei Alexandrescu,如今已經(jīng)成為D語言的領(lǐng)袖人物之一。

同時(shí),Andrei Alexandrescu還將圍繞大 規(guī)模并行計(jì)算時(shí)代可能會(huì)出現(xiàn)的危險(xiǎn)的并發(fā)錯(cuò)誤、死鎖 和效率損失帶來“Lock-Free Data Structures(無鎖數(shù)據(jù)結(jié)構(gòu))”的講座。現(xiàn)在人們已經(jīng)認(rèn)為,傳統(tǒng)的基于共享資源加鎖的編程方法有如老牛破車,已經(jīng)注定將被打入冷宮。而Lock-Free數(shù)據(jù)結(jié)構(gòu)和CAS指令為高效并行計(jì)算開辟了新的途 徑。Andrei Alexandrescu將深入淺出地介紹Lock-Free數(shù)據(jù)結(jié)構(gòu)的概念、意義和用法,并將該技術(shù)在C++中的實(shí)現(xiàn)方法和盤托出。

Andrei Alexandrescu是一位技術(shù)專家,同時(shí)他還擁有多種身份:華爾街咨詢師,搖滾樂隊(duì)鼓手,古典吉他演奏家,羅馬尼亞傘兵。相信傾聽這樣一位天才級(jí)的技術(shù)高手,與之坐而論道是一種享受。

]]>
C++:最強(qiáng)大的.NET語言之內(nèi)存與資源http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2438&Page=1wangxinxin2010-12-10 15:10:38IT168技術(shù)文檔】

    當(dāng)運(yùn)行環(huán)境中包含垃圾回收機(jī)制時(shí),區(qū)別開內(nèi)存管理和資源管理,就非常重要了。典型地來說,垃圾回收器只對(duì)包含對(duì)象的內(nèi)存之分配與釋放感興趣,它可不關(guān)心你的對(duì)象是否擁有其他的資源,如數(shù)據(jù)庫連接或核心對(duì)象的句柄。

    內(nèi)存管理

    本地C++為程序員提供了超越內(nèi)存管理的直接控制能力,在堆棧上分配一個(gè)對(duì)象,意味著只有在進(jìn)入特定函數(shù)時(shí),才會(huì)為對(duì)象分配內(nèi)存,而當(dāng)函數(shù)返回或堆棧展開時(shí),內(nèi)存被釋放。可使用操作符new來動(dòng)態(tài)地為對(duì)象分配內(nèi)存,此時(shí)內(nèi)存分配在CRT堆中,并且需要程序員顯存地對(duì)對(duì)象指針使用操作符delete,才能釋放它。這種對(duì)內(nèi)存的精確控制,也是C++可用于編寫極度高效的程序的原因之一,但如果程序員不小心,這也是內(nèi)存泄漏的原因。另一方面,你不需要求助于垃圾回收器來避免內(nèi)存泄漏--實(shí)際上這是CLR所采取的方法,而且是一個(gè)非常有效的方法,當(dāng)然,對(duì)于垃圾回收堆,也有其他一些好處,如改進(jìn)的分配效率及引用位置相關(guān)的優(yōu)勢(shì)。所有這一切,都可以在C++中通過庫支持來實(shí)現(xiàn),但除此之處,CLR還提供了一個(gè)單一的內(nèi)存管理編程模型,其對(duì)所有的編程語言都是通用的,想一想與C++中COM自動(dòng)化對(duì)象相交互和調(diào)度數(shù)據(jù)類型所需做的一切工作,就會(huì)發(fā)現(xiàn)其重要意義所在--橫跨數(shù)種編程語言的垃圾回收器,作用是非常巨大的。

    為了效率,CLR也保留了堆棧的概念,以便值類型可在其上分配,但CLR也提供了一個(gè)newobj中間語言指令,以在托管堆中分配一個(gè)對(duì)象,但此指令只在C#中對(duì)引用對(duì)象使用操作符new時(shí)提供。在CLR中,沒有與C++中的delete操作符對(duì)應(yīng)的函數(shù),當(dāng)應(yīng)用程序不再引用某對(duì)象時(shí),分配的內(nèi)存最后將由垃圾回收器回收。

    當(dāng)操作符new應(yīng)用于引用類型時(shí),托管C++也會(huì)生成newobj指令,當(dāng)然,對(duì)此使用delete操作符是不合法的。這確實(shí)是一個(gè)矛盾,但同時(shí)也證明了為什么用C++指針概念來表示一個(gè)引用類型不是一個(gè)好的做法。

    在內(nèi)存管理方面,除了上述在對(duì)象構(gòu)造一節(jié)討論過的內(nèi)容,C++/CLI沒有提供任何新的東西;資源管理,才是C++/CLI的拿手好戲。

    資源管理

    CLR只有在資源管理方面,才能勝過本地C++。Bjarne Stroustrup的"資源獲取即初始化"的技術(shù)觀點(diǎn),基本定義了資源類型的模式,即類的構(gòu)造函數(shù)獲取資源,析構(gòu)函數(shù)釋放資源。這些類型是被當(dāng)作堆棧上的局部對(duì)象,或復(fù)雜類型中的成員,其析構(gòu)函數(shù)自動(dòng)釋放先前分配的資源。一如Stroustrup所言"對(duì)垃圾回收機(jī)制來說,C++是最好的語言,主要是因?yàn)樗珊苌俚睦?

    也許有一點(diǎn)令人驚訝,CLR并沒有對(duì)資源管理提供任何顯式運(yùn)行時(shí)支持,CLR不支持類似析構(gòu)函數(shù)的C++概念,而是在 .NET Framework中,把資源管理這種模式,提升到一個(gè)IDisposable核心接口類型的中心位置。這種想法源自包裝資源的類型,理應(yīng)實(shí)現(xiàn)此接口的單一Dispose方法,以便調(diào)用者在不再使用資源時(shí),可調(diào)用該方法。不必說,C++程序員會(huì)認(rèn)為這是時(shí)代的倒退,因?yàn)樗麄兞?xí)慣于編寫那些缺省狀態(tài)下清理就是正確的代碼。

    因?yàn)楸仨氁{(diào)用一個(gè)方法來釋放資源,由此帶來的問題是,現(xiàn)在更難編寫"全無異常"的代碼了。因?yàn)楫惓kS時(shí)都可能發(fā)生,你不可能只是簡(jiǎn)單地在一段代碼后,放置一個(gè)對(duì)對(duì)象的Dispose方法的調(diào)用,這樣做的話,就必須要冒資源泄漏的風(fēng)險(xiǎn)。在C#中解決這個(gè)問題的辦法是,使用try-finally塊和using語句,在面對(duì)異常時(shí),可提供一個(gè)更可靠的辦法來調(diào)用Dispose方法。有時(shí),構(gòu)造函數(shù)也會(huì)使用這種方法,但一般的情況是,你必須要記住手工編寫它們,如果忘記了,生成的代碼可能會(huì)存在一個(gè)悄無聲息的錯(cuò)誤。對(duì)缺乏真正析構(gòu)函數(shù)的語言來說,是否需要try-finally塊和using語句,還有待論證。

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->using (SqlConnection connection = new SqlConnection("Database=master; Integrated Security=sspi")) ...{  SqlCommand command = connection.CreateCommand();  command.CommandText = "sp_databases";  command.CommandType = CommandType.StoredProcedure;  connection.Open();  using (SqlDataReader reader = command.ExecuteReader())  ...{   while (reader.Read())   ...{    Console.WriteLine(reader.GetString(0));   }  } }

    對(duì)托管C++來說,情節(jié)也非常類似,也需要使用一個(gè)try-finally語句,但其是Microsoft對(duì)C++的擴(kuò)展。雖然很容易編寫一個(gè)簡(jiǎn)單的Using模板類來包裝GCHandle,并在模板類的析構(gòu)函數(shù)中調(diào)用托管對(duì)象的Dispose方法,但托管C++中依然沒有C# using語句的對(duì)等物。 

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->Using<SqlConnection> connection(new SqlConnection(S"Database=master; Integrated Security=sspi")); SqlCommand* command = connection->CreateCommand(); command->set_CommandText(S"sp_databases"); command->set_CommandType(CommandType::StoredProcedure); connection->Open(); Using<SqlDataReader> reader(command->ExecuteReader()); while (reader->Read()) ...{  Console::WriteLine(reader->GetString(0)); }
]]>
目前主流開發(fā)技術(shù)的分析和總結(jié)http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2437&Page=1wangxinxin2010-12-10 15:09:35
  桌面應(yīng)用程序框架:MFC、VCL、QT、JavaAWTSWING、.Net

  企業(yè)應(yīng)用程序框架:WindowsDNA(ASP、COM、COM+)、J2EE、.NetFramework

  開發(fā)工具:VisualBasic、Delphi、VisualC++、C++Builder、VisualC#

  *程序設(shè)計(jì)語言:C++Delphi(本來應(yīng)該是ObjectPascal,但為了簡(jiǎn)單,我就語言和工具混為一談吧)JavaC#(雖然他剛剛推出,但因?yàn)槲④洖橹畠A注了大量心血,一定會(huì)成為一種重要的開發(fā)語言)

  *桌面應(yīng)用程序框架:MFCVCL

  *企業(yè)應(yīng)用程序框架:WindowsDNAJ2EE.Net

  *COM技術(shù):我單獨(dú)提出這項(xiàng)技術(shù),是因?yàn)樗鼰o法簡(jiǎn)單的被視為語言、桌面應(yīng)用程序框架或企業(yè)應(yīng)用程序框架,它與這些都有關(guān)系。

  2.1 程序設(shè)計(jì)語言

  2.1.1 C++語言的演進(jìn)

  最初要從二進(jìn)制代碼和匯編說起,但那太遙遠(yuǎn)了。我們就從面向過程的語言說起吧(包括BasicCFortranPascal)。這種面向過程的高級(jí)語言終于把計(jì)算機(jī)帶入了尋常的應(yīng)用領(lǐng)域。其中的C語言因?yàn)樗暮?jiǎn)單和靈活造就了Unix和Windows這樣的偉大的軟件。

  面向?qū)ο蟮恼Z言是計(jì)算機(jī)語言的一個(gè)合乎邏輯的進(jìn)化,因?yàn)樵跊]有過多的影響效率、簡(jiǎn)單性的前提下提供了一種更好的組織數(shù)據(jù)的方法,可使程序更容易理解,更容易管理——這一點(diǎn)可能會(huì)引出不同意見,但事實(shí)勝于雄辯,C++終于讓C語言的領(lǐng)地越來越小,當(dāng)今還活著的計(jì)算機(jī)語言或多或少的都具備面向?qū)ο蟮奶卣鳎赃@一點(diǎn)并不會(huì)引起太多困惑。C++的成功很大程度要?dú)w因于C,C++成為它今天的樣子是合乎邏輯的產(chǎn)物。因?yàn)樵诿嫦蜻^程的時(shí)代,C幾乎已經(jīng)統(tǒng)一天下了。今天著名的語言象JavaC#都從C借鑒了很多東西,C#本來的意思就是C++++。其實(shí)C++曾經(jīng)很有理由統(tǒng)一面向?qū)ο蟪绦蛟O(shè)計(jì)語言的天下來著,但可惜的是,C++太復(fù)雜了。即使是一個(gè)熟練的程序員,要你很清楚的解釋一些問題你也會(huì)很頭痛。舉幾個(gè)還不是那么復(fù)雜的例子來說:

  對(duì)=的重載成員轉(zhuǎn)換函數(shù)拷貝構(gòu)造函數(shù)轉(zhuǎn)化構(gòu)造函數(shù)之間有什么區(qū)別和聯(lián)系呢?

  定義一個(gè)類成員函數(shù)private:virtualvoidMemFun()=0;是什么意義呢?

  int(*(*x(int))[4])(double);是什么意思?

  還有其他的特征,比如說可以用來制造一種新語言的typedef和宏(雖然宏不是C++的一部分,但它與C++的關(guān)系實(shí)在太密切了),讓你一不小心就摔跤的內(nèi)存問題(只要new和delete就可以了嗎?有沒有考慮一個(gè)對(duì)象存放在容器中的情況?)……諸如此類,C++是如此的復(fù)雜以至于要學(xué)會(huì)它就需要很長(zhǎng)的時(shí)間,而且你會(huì)發(fā)現(xiàn)即使你用C++已經(jīng)好幾年了,你還會(huì)發(fā)現(xiàn)經(jīng)常有新東西可學(xué)。你想解決一個(gè)應(yīng)用領(lǐng)域的問題——比如說從數(shù)據(jù)庫里面查詢數(shù)據(jù)、更改數(shù)據(jù)那樣的問題,可是你卻需要首先為C++頭痛一陣子才可以,是的,你精通C++,你可以很容易的回答我的問題,可是你有沒有想過你付出了多大的代價(jià)呢?我不是想過分的譴責(zé)C++,我本人喜歡C++,我甚至建議一個(gè)認(rèn)真的開發(fā)普通的應(yīng)用系統(tǒng)的程序員也去學(xué)習(xí)一下C++,C++中的一些特性,比如說指針運(yùn)算模板STL幾乎讓人愛不釋手,宏可以用幾個(gè)字符代替很多代碼,對(duì)系統(tǒng)級(jí)的程序員來說,C++的地位是不可替代的,Java的虛擬機(jī)就是C++寫的。C++還將繼續(xù)存在而且有旺盛的生命力。

  2.1.2 Java和C#

  Java和C#相對(duì)于C++的不同最大的有兩點(diǎn):第一點(diǎn)是他們運(yùn)行在一個(gè)虛擬環(huán)境之中,第二點(diǎn)是語法簡(jiǎn)單。對(duì)于開發(fā)人員而言,在語法和語言機(jī)制的角度可以把Java和C#視為同一種語言。C#更多的是個(gè)政治的產(chǎn)物而不是技術(shù)產(chǎn)物。如果不是Sun為難微軟的話,我想微軟不會(huì)費(fèi)盡心力推出一個(gè)和Java差不多的C++++,記得Visual J++嗎,記得WFC嗎?看看那些東西就會(huì)知道微軟為Java曾經(jīng)傾注了多少心血。而且從更廣泛的角度來說,兩者也是非常相似的——C#和Java面對(duì)的是同樣的問題,面向應(yīng)用領(lǐng)域的問題:事務(wù)處理、遠(yuǎn)程訪問、Webservice、Web頁面發(fā)布、圖形界面。那么在這一段中,我暫且用Java這個(gè)名字指代Java和C#兩種語言——盡管兩者在細(xì)節(jié)上確實(shí)有區(qū)別。Java是適合解決應(yīng)用領(lǐng)域的問題的語言。最大的原因Java對(duì)于使用者來說非常簡(jiǎn)單。想想你學(xué)會(huì)并且能夠使用Java需要多長(zhǎng)時(shí)間,學(xué)會(huì)并且能夠使用C++要多長(zhǎng)時(shí)間。由于Java很大程度上屏蔽了內(nèi)存管理問題,而且沒有那么多為了微小的性能提升定義的特殊的內(nèi)容(比如說,在Java里面沒有virtual這個(gè)關(guān)鍵字,Java也不允許你直接在棧上創(chuàng)建對(duì)象,Java明確的區(qū)分bool和整型變量),他讓你盡量一致的方式操作所有的東西,除了基本數(shù)據(jù)類型,所有的東西都是對(duì)象,你必須通過引用來操 作他們;除了這些之外,Java還提供了豐富的類庫幫助你解決應(yīng)用問題——因?yàn)樗敲嫦驊?yīng)用的語言,它為你提供了多線程標(biāo)準(zhǔn)、JDBC標(biāo)準(zhǔn)、GUI標(biāo)準(zhǔn),而這些標(biāo)準(zhǔn)在C++中是不存在的,因?yàn)镃++并不是直接面向解決應(yīng)用問題的用戶,有人試圖在C++中加入這些內(nèi)容,但并不成功,因?yàn)镃++本身太復(fù)雜了,用這種復(fù)雜的語言來實(shí)現(xiàn)這種復(fù)雜的應(yīng)用程序框架本身就是一件艱難的事情,稍后我們會(huì)提到這種嘗試——COM技術(shù)。漸漸的,人們不會(huì)再用C++開發(fā)應(yīng)用領(lǐng)域的軟件,象MFCQTCOM這一類的東西最終也將退出歷史舞臺(tái)。

  2.1.3 Delphi

  Delphi是從用C++開發(fā)應(yīng)用系統(tǒng)轉(zhuǎn)向用Java開發(fā)應(yīng)用系統(tǒng)的一個(gè)中間產(chǎn)物。它比C++簡(jiǎn)單,簡(jiǎn)單的幾乎象Java一樣,因?yàn)樗暮?jiǎn)單,定義和使用豐富的類庫成為可能,而且Delphi也這么做了,結(jié)果就是VCL和其他的組件庫。而另一方面,它又比運(yùn)行于虛擬環(huán)境的Java效率要高一些,這樣在簡(jiǎn)單性和效率的平衡之中,Delphi找到了自己的生存空間。而且預(yù)計(jì)在未來的一段時(shí)間之內(nèi),這個(gè)生存空間將仍然是存在的。可以明顯的看出,微軟放棄了這個(gè)領(lǐng)域,他專注于兩方面:系統(tǒng)語言C++和未來的Java(其實(shí)是.Net)。也許這對(duì)于Borland來說,是一件很幸運(yùn)的事情。如果我能夠給Borland提一些建議的話,那就是不要把Delphi弄得越來越復(fù)雜,如果那樣,就是把自己的用戶趕到了C++或Java的領(lǐng)地。在虛擬機(jī)沒有最終占領(lǐng)所有的應(yīng)用程序開發(fā)領(lǐng)域之前,Delphi和Delphi的用戶仍然會(huì)生存得很好。

  2.2桌面應(yīng)用程序框架

  目前真正成功的桌面應(yīng)用程序框架只有兩個(gè),一個(gè)是MFC,一個(gè)是VCL,還有一些其他的,但事實(shí)上并未進(jìn)入應(yīng)用領(lǐng)域。遺憾的是我對(duì)兩個(gè)桌面應(yīng)用程序框架都不精通。但這不妨礙我對(duì)他做出正確的評(píng)價(jià)。

  2.2.1MFC

  MFC(還有曾經(jīng)的OWL)是SDK編程的正常演化的結(jié)果,就象是C++是C的演化結(jié)果一樣。MFC本身是一件了不起但不那么成功的作品,而且它過時(shí)了。這就是我的結(jié)論。MFC凝聚了很多天才的智慧——當(dāng)然,OWL和VCL也一樣,侯捷的《深入淺出MFC》把這些智慧擺在了我們的面前。但是這件東西用起來估計(jì)不會(huì)有人覺得很舒服,如果你一直在用Java、VB或者Delphi,再回過頭來用MFC,不舒服的感覺會(huì)更加強(qiáng)烈。我不能夠解釋MFC為什么沒有能夠最終發(fā)展成和VCL一樣簡(jiǎn)單好用的桌面程序框架,也許是微軟沒精力或者沒動(dòng)力,總之MFC就是那個(gè)樣子了,而且也不會(huì)再有發(fā)展,它已經(jīng)被拋棄了。我有時(shí)候想,也許基于C++這種復(fù)雜的語言開發(fā)MFC這樣的東西本身就是錯(cuò)誤的——可以開發(fā)這樣的一個(gè)框架,但不應(yīng)當(dāng)要求使用它的人熟悉了整個(gè)框架之后才能夠使用這個(gè)系統(tǒng),但很顯然,如果你不了解MFC的內(nèi)部機(jī)制,是不太可能把它用好的,我不能解釋清楚為什么會(huì)出現(xiàn)這種現(xiàn)象。

  2.2.2VCL

  相比之下VCL要成功的得多。我相信很多使用VCL的人可能沒有像MFC的用戶研究MFC那樣費(fèi)勁的研究過VCL的內(nèi)部機(jī)制。但這不妨礙他們開發(fā)出好用好看的應(yīng)用程序,這就足夠了,還有什么好說的呢?VCL給你提供了一種簡(jiǎn)單一致的機(jī)制,讓你可以寫出復(fù)雜的應(yīng)用程序。在李維的Borland故事那篇文章中曾經(jīng)說過,在Borland C++ 3.1推出之后Borland就有人提出開發(fā)類似C++ Builder一類的軟件,后來竟未成行。是啊,如果C++ Builder是在那個(gè)時(shí)候出現(xiàn)的,今天的軟件開發(fā)領(lǐng)域?qū)?huì)是怎么樣的世界呢?真的不能想象。也許再過一段時(shí)間,這些都將不再重要。因?yàn)樾律恼Z言如Java和C#都提供了類似于VCL的桌面應(yīng)用程序框架。那個(gè)時(shí)候,加上Java和C#本身的簡(jiǎn)單性,如果他們的速度有足夠塊,連Delphi這種語言也要消失了,還有什么好爭(zhēng)論的呢?只是對(duì)于今天的桌面程序開發(fā)人員來說,VCL確實(shí)是最好的選擇]]>
C++與Java語言及其開發(fā)工具http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2436&Page=1wangxinxin2010-12-10 15:08:03
一、Java語言 

Java是由Sun公司的一個(gè)技術(shù)小組研制出來的。在實(shí)現(xiàn)Java語言的過程中,小組的技術(shù)人員很快就意識(shí)到:C++無法成為一種完全面向?qū)ο蟮摹⒕W(wǎng)絡(luò)化的開發(fā)語言。C++是通過給原先的C語言增加面向?qū)ο蠊δ芏_發(fā)出來的,因此,它存在著先天不足。這主要體現(xiàn)在C++種類繁多,功能大量冗余,同時(shí)又沒有任何一種C++編譯器能夠支持它的全部功能。鑒于這種情況,Sun公司的技術(shù)人員決定不擴(kuò)充C++,而開發(fā)一種全新的計(jì)算機(jī)語言(Java的前身Oak)。但是,C++已經(jīng)成了大多數(shù)編程人員所熟練掌握的語言,Java的設(shè)計(jì)顯然不能無視這個(gè)現(xiàn)實(shí)。如果Java和C++之間的差別
過大,那么程序員們?cè)趯W(xué)會(huì)這種語言的過程中無疑要花費(fèi)大量的時(shí)間和精力。因此,Java保留了盡可能多的C++風(fēng)格。 

Java是完全面向?qū)ο蟮?這和C++不盡相同。盡管C++被認(rèn)為是一種面向?qū)ο蟮恼Z言,但它仍然支持過程式程序設(shè)計(jì)風(fēng)格。Java則不然,它要求程序員采用完全面向?qū)ο蟮木幊碳夹g(shù) ,從而消除了由于混用兩種相同的編程風(fēng)格而導(dǎo)致的種種問題。另一方面,Java的"外觀"和 "感覺"和C++又有著很多相似之處。Java消除了C和C++中的冗余以及所有過程式的編程風(fēng)格 ,并且不再支持指針數(shù)據(jù)類型,同時(shí)增加了數(shù)組的自動(dòng)邊界檢查和自動(dòng)內(nèi)存垃圾搜集,并且把數(shù)組封裝到類結(jié)構(gòu)內(nèi),從而有助于開發(fā)分布計(jì)算環(huán)境下的應(yīng)用程序。 

不過,Java之所以能夠成為一種理想的編程語言,最重要的原因還在于其"內(nèi)嵌"的內(nèi)存管理和多線索功能。C++語言支持程序員編寫一些非常低級(jí)的程序,從而能夠訪問機(jī)器硬件 ,并操縱實(shí)際內(nèi)存地址。但這些是以犧牲可移植性為代價(jià)的,因?yàn)檫@時(shí)每個(gè)程序都是針對(duì)某種具體硬件環(huán)境的。而Java卻是通過提供各種邊界檢查和內(nèi)存管理來確保代碼的可移植性 ,同時(shí),還提供了內(nèi)嵌的多線索功能,使類似于內(nèi)存垃圾搜集一類的操作可以在后臺(tái)進(jìn)行,從而保證了較高的執(zhí)行效率。 

Java語言能夠具有這些優(yōu)點(diǎn),主要是因?yàn)樗亲鳛橐环N全新的語言而設(shè)計(jì)的。如果僅僅是擴(kuò)充C++,Java將無法避免C++中遺留的大量過程式特性,其解釋器的規(guī)模將急劇增長(zhǎng),從而降低了系統(tǒng)的總體性能,代碼的可移植性和穩(wěn)定性的實(shí)現(xiàn)即使是可能的,也將非常困難。總之,Java的這些特性,為其成為下一代編程語言奠定了良好的基礎(chǔ)。 

1.Java 的面向?qū)ο筇卣?nbsp;

面向?qū)ο蠹夹g(shù)的關(guān)鍵在于封裝、繼承和動(dòng)態(tài)聯(lián)編,下面就談?wù)凧ava是如何支持這些關(guān)鍵特性的。 

面向?qū)ο蠹夹g(shù)的基本單位是對(duì)象,對(duì)象在Java中稱為類(Class)。一個(gè)類實(shí)際上就是一段用于實(shí)現(xiàn)對(duì)象行為的代碼,它是提供封裝性的根本所在。也就是說,對(duì)象及其相關(guān)的所有操作均被封裝到一個(gè)類中。 

所有的對(duì)象都有一個(gè)狀態(tài)。類也有狀態(tài),以"實(shí)例變量"表示。實(shí)例變量由相應(yīng)的類進(jìn)行控制,除某些特殊情況外其它任何類都無法訪問這些變量。實(shí)例變量通過方法(method)進(jìn)行訪問。方法相當(dāng)于過程式語言中的函數(shù),它是一個(gè)可多次調(diào)用的代碼段。程序員必須通過調(diào)用方法來實(shí)現(xiàn)對(duì)類的控制,即改變類的狀態(tài),而且只能實(shí)現(xiàn)類的方法所允許的操作。這就是面向?qū)ο蠹夹g(shù)的工作原理。 

當(dāng)然,在個(gè)別情況下(對(duì)某些面向?qū)ο蟮恼Z言而言),編程人員也可以直接訪問實(shí)例變量 ,但這并不是一個(gè)值得推薦的做法,因?yàn)樗`背了面向?qū)ο蟮某踔浴?nbsp;

面向?qū)ο缶幊痰膬?yōu)點(diǎn)主要在于代碼的可重用性。當(dāng)需要進(jìn)行某些重復(fù)性操作時(shí),編程人員不必反復(fù)地重寫相同的代碼段,而只需創(chuàng)建對(duì)象的多個(gè)實(shí)例即可。因?yàn)榫幊倘藛T既不需要了解對(duì)象是如何創(chuàng)建的,也不用知道對(duì)象內(nèi)部的工作機(jī)理,需要知道的只是對(duì)象方法的調(diào)用機(jī)制,其余的工作將由對(duì)象所屬的類進(jìn)行處理。在Java中,程序員可以編寫完成各種功能的類,發(fā)布編譯之后的代碼,并且只需要告訴用戶如何控制這些類即可。 

Java通過類來實(shí)現(xiàn)對(duì)象,并且提供了類的多種用法。類可以作為各對(duì)象實(shí)例的一個(gè)模板。為創(chuàng)建類的新實(shí)例,可以調(diào)用其構(gòu)造函數(shù),它是每當(dāng)創(chuàng)建類的一份新的拷貝時(shí)都必須調(diào)用的一個(gè)特殊方法。當(dāng)一個(gè)類的所有程序都已經(jīng)結(jié)束運(yùn)行,或者Java覺得不再需要調(diào)用該類時(shí) (比方說應(yīng)用程序已經(jīng)結(jié)束),必須調(diào)用這個(gè)類的終結(jié)函數(shù)(finalize),以進(jìn)行一些必要的清除工作。當(dāng)然,Java的終結(jié)函數(shù)和C++中的析構(gòu)函數(shù)會(huì)有所差別,因?yàn)镴ava可進(jìn)行自動(dòng)垃圾清除。]]>
增強(qiáng)Visual C++開發(fā)環(huán)境_VC技術(shù)_C語言教程http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2435&Page=1wangxinxin2010-12-10 15:05:00       程序和軟件都是使用它來開發(fā)出來的。VC的開發(fā)環(huán)境提供了強(qiáng)大的功能,為開發(fā)人員方便、快速、高效地開發(fā)應(yīng)用給予了強(qiáng)有力的支持。但是由于程序員各有各的特點(diǎn)和習(xí)慣,所以還可能會(huì)有很多對(duì)編程開發(fā)環(huán)境不同的需要。VC的IDE集成開發(fā)環(huán)境充分考慮到了這一點(diǎn),專門提供了對(duì)開發(fā)環(huán)境進(jìn)行擴(kuò)展的功能,使得開發(fā)員可以根據(jù)需要,通過一些編程開發(fā)來增強(qiáng)VC開發(fā)環(huán)境本身的功能。

Visual C++的自動(dòng)化機(jī)制
  在使用VC來進(jìn)行開發(fā)的時(shí)候,在VC的集成開發(fā)環(huán)境里可以手工進(jìn)行很多操作,例如:使用菜單命令來打開一個(gè)項(xiàng)目、修改源文件、保存文件,然后編譯連接得到可執(zhí)行的文件等等。這些操作大部分都是例行的、重復(fù)多次進(jìn)行的。

  VC提供了一種Automation自動(dòng)化(來自以前的OLE自動(dòng)化)的擴(kuò)展機(jī)制。VC的開發(fā)者可以通過開發(fā)VBScript宏或者插件,讓IDE來自動(dòng)執(zhí)行一些操作。好處是顯然的:可以大大縮短這些操作的時(shí)間,而且還可以避免在手工操作可能出現(xiàn)的一些錯(cuò)誤,如遺漏、鍵入錯(cuò)誤等等。VBScript宏是使用VBScript語言寫的一些程序,而插件則是使用VC或者Visual Basic開發(fā)的COM構(gòu)件。

  我們還可以使用VBScript宏和插件來對(duì)VC本身的界面進(jìn)行美化、改造,例如為VC的窗口加上頁簽(與Delphi的界面類似)等等。

  在宏或者插件里,VC的集成開發(fā)環(huán)境本身以及它的各個(gè)部件都可以作為對(duì)象來進(jìn)行操作。例如,通過操作與項(xiàng)目的文件對(duì)應(yīng)的對(duì)象,可以對(duì)某個(gè)文件進(jìn)行打開、編輯和關(guān)閉等操作。類似的,操作與IDE中的窗口對(duì)應(yīng)的對(duì)象,可以激活一個(gè)窗口、改變窗口的大小等等。

  一個(gè)對(duì)象可以是集成開發(fā)環(huán)境的一個(gè)部件,或者一組相關(guān)的部件。例如,一個(gè)Document文件對(duì)象表示一個(gè)打開的文件,而Documents對(duì)象則表示所有打開的文件。類似,一個(gè)Window窗口對(duì)象表示一個(gè)打開的窗口,而Windows對(duì)象表示所有打開的窗口。Documents和Windows對(duì)象稱為集合對(duì)象,它們包含了相關(guān)的一組對(duì)象。

  每一個(gè)IDE環(huán)境的對(duì)象都實(shí)現(xiàn)了一個(gè)雙向的接口,提供了大量的方法、屬性和事件,在開發(fā)VBScript宏和插件的時(shí)候需要使用這些方法、屬性和事件來操作這些對(duì)象。同時(shí),每一個(gè)對(duì)象為Automation機(jī)制實(shí)現(xiàn)了一個(gè)IDispatch接口和一個(gè)COM接口,來支持對(duì)對(duì)象成員(屬性、方法和事件)的訪問。

  為了更好地操作集成開發(fā)環(huán)境的對(duì)象,必須知道這些對(duì)象之間的關(guān)系。對(duì)象之間有一個(gè)層次包含的關(guān)系。Application對(duì)象是最頂層的,其它的對(duì)象都是從屬于它的。有了這個(gè)關(guān)系,就可以使用Application對(duì)象的屬性和方法來直接訪問它的所有下屬對(duì)象啦!VC集成開發(fā)環(huán)境的對(duì)象以及它們之間的包含關(guān)系如下:
Application
Application(Application也可以包含自己)
Projects
Project
Configurations
Configuration
Configurations(循環(huán))
Documents
Document
Window(一般窗口)
TextDocument
TextSelection
TextWindow
Window(文本窗口)
TextEditor
Windows
Debugger
Breakpoints
Breakpoint

  例如,Breakpoints對(duì)象有一個(gè)Breakpoint對(duì)象作為它的屬性之一,也就是說Breakpoints對(duì)象包含了一個(gè)或者多個(gè)Breakpoint對(duì)象。這樣就可以通過一個(gè)對(duì)象的屬性來訪問它包含的所有下屬對(duì)象。反過來,也可以通過一個(gè)對(duì)象的Parent屬性來訪問它所屬的對(duì)象。

  VC這種環(huán)境的對(duì)象封裝機(jī)制為我們開發(fā)VBScript宏和插件來擴(kuò)展VC集成開發(fā)環(huán)境的功能提供了極大的方便。下面就讓我們具體看看怎樣來開發(fā)VBScript宏和插件,利用VC的Automation機(jī)制,增強(qiáng)VC開發(fā)環(huán)境的功能,以方便自己日常的開發(fā)工作。

VBScript宏
VBScript宏是使用VBScript語言寫的不帶參數(shù)的過程。VBScript宏不單單可以用在VC里,在微軟的Office工具里也可以使用。我們可以使用宏來極大地簡(jiǎn)化VC里的一些工作,例如組合一些命令、進(jìn)行一些快速編輯或者自動(dòng)進(jìn)行一些復(fù)雜的處理等等。VBScript宏以Sub語句開始,然后是執(zhí)行一些操作的VBScript語句,以End Sub語句結(jié)束。

我們先來看一個(gè)具體的宏。下面是快速創(chuàng)建一個(gè)C/C++文件的VBScript宏。
Sub CreateCPPFile
Set CPPDoc = Document.Add("Text")
CPPDoc.Language = dsCPP
End Sub

從這個(gè)簡(jiǎn)單的宏,我們可以看到:
* Sub語句開始一個(gè)宏的定義,這個(gè)宏的名字是CreateCPPFile。宏的名字是任意的,可以選擇易于記憶的名字。
* 宏的第一行使用Documents對(duì)象的Add方法,往Documents對(duì)象里增加了一個(gè)Document對(duì)象,從而創(chuàng)建了一個(gè)新文件。
* 宏的第二行通過設(shè)置Document對(duì)象的Language屬性為常量dsCPP(代表C/C++),指定該文件的類型是C/C++文件。
* End Sub語句結(jié)束這個(gè)宏。
得到一個(gè)VBScript宏有兩個(gè)途徑:記錄或者手工書寫。最簡(jiǎn)單、最容易的方法當(dāng)然是記錄啦!在你記錄一個(gè)宏的時(shí)候,宏記錄器跟蹤你的動(dòng)作,把這些動(dòng)作轉(zhuǎn)換成VBScript語句,然后把這些語句插入到宏里面。

  VC提供了兩種宏記錄的方法:正常宏記錄和快速宏記錄。
快速宏記錄則可以快速記錄你的一些動(dòng)作,而不需要命名、描述或者編輯這個(gè)宏,但是只可以保存一個(gè),重新記錄將刪掉原來的快速宏。記錄快速宏的簡(jiǎn)單過程如下:(1)選擇Tools菜單里的Record Quick Macro命令;(2)執(zhí)行需要記錄的動(dòng)作,在執(zhí)行動(dòng)作的過程中可以使用宏記錄器工具條上的Pause暫停按鈕來臨時(shí)中斷記錄或者繼續(xù)記錄;(3)完成所有動(dòng)作后,點(diǎn)擊宏記錄器工具條上的Stop按鈕即可。需要使用這個(gè)快速宏,選擇Tools菜單的Play Quick Macro命令即可。

  如果你想要記錄一個(gè)復(fù)雜的宏,而且要進(jìn)行一些編輯,那就要使用正常的宏記錄了。錄制正常宏的過程如下:(1)選擇Tools菜單的Macro命令打開宏管理器,如圖1所示;(2)如果需要把宏加到一個(gè)新的宏文件里,點(diǎn)擊Options按鈕,點(diǎn)擊New File按鈕,然后在Macro File框里填入文件名字;如果需要把宏加到一個(gè)已有的文件里,則從Macro File的下拉框里選擇文件;(3)在Macro Name框里寫入宏的名字;(4)點(diǎn)擊Record按鈕;(5)在Add Macro對(duì)話框里寫入宏的描述,點(diǎn)擊OK按鈕;(5)執(zhí)行需要記錄的動(dòng)作,中間可以點(diǎn)擊Pause按鈕暫停或者繼續(xù);(6)點(diǎn)擊Stop按鈕完成錄制,這時(shí)候VC將打開宏文件,并且把光標(biāo)停在宏的起始點(diǎn),你可以對(duì)宏進(jìn)行檢查或者編輯。

圖1
  也可以往一個(gè)新的或者已有的宏文件里添加代碼,直接手工寫一個(gè)宏。步驟如下:(1)選擇Tools菜單的Macro命令打開宏管理器;(2)選擇宏文件或者新建宏文件;(3) 在Macro Name框里寫入宏的名字;(4)點(diǎn)擊Edit按鈕;(5)在Add Macro對(duì)話框里寫入宏的描述,點(diǎn)擊OK按鈕,VC將打開宏文件,在文件的尾部為新的宏創(chuàng)建一個(gè)架子-Sub塊,如下所示(假設(shè)宏的名字為MyMacro):
Sub MyMacro()
'Description: The macro description goes here
'TODO: Insert the macro code here.
//這一段是自己編寫的,為選中的文本加C語言的注釋符號(hào)
ActiveDocument.Selection = "/*" + ActiveDocument.Selection + "*/"
End Sub
你就可以往這個(gè)架子里填寫入具體操作了。

  在記錄或者編寫好宏以后,宏將被保存在一個(gè)文本文件-宏文件里。在你開始記錄或者編寫新的宏的時(shí)候,需要選擇宏文件。宏文件的擴(kuò)展名為.DSM,包含了一個(gè)或者多個(gè)VBScript宏,數(shù)量看需要而定。宏文件的一般格式是:開始是對(duì)這個(gè)文件的一些描述,然后就是每個(gè)宏的具體定義。

  在VC里使用宏文件需要先安裝。一旦安裝了以后,每次啟動(dòng)VC的時(shí)候都會(huì)自動(dòng)裝載這些宏,可以在所有的項(xiàng)目里使用,不依賴于項(xiàng)目。安裝宏文件的方法如下:(1)選擇Tools菜單的Customize命令;(2)選擇Add-ins and Macro Files頁簽,如圖2所示,如果宏文件的名字沒有出現(xiàn)在窗口里,則點(diǎn)擊Browse按鈕去定位。(3)在窗口里打勾選上需要安裝的宏文件即可;如果取消選擇某個(gè)宏文件,則會(huì)卸載這個(gè)宏文件。

圖2
  有了VBScript宏,只要運(yùn)行它即可以自動(dòng)幫你完成所需要的操作啦!如果需要經(jīng)常運(yùn)行某個(gè)宏,那么可以為這個(gè)宏分配一個(gè)工具條按鈕或者熱鍵,這樣就可以通過點(diǎn)擊按鈕或者按熱鍵方便地運(yùn)行這個(gè)宏了。分配按鈕的具體設(shè)置是:(1)選擇Tools按鈕的Customize命令;(2)選擇Commands頁簽;(3)在Category框里選擇Macros;(4)在Commands框里,把要分配工具條按鈕的宏直接拖放到工具條上;(5)這時(shí)會(huì)彈出一個(gè)Button Appearance對(duì)話框,如圖3所示,為這個(gè)按鈕選擇一個(gè)合適的位圖,點(diǎn)擊OK即可,VC將在工具條上添加上這個(gè)宏的一個(gè)按鈕。分配熱鍵的方法是:(1)選擇Tools按鈕的Customize命令;(2)選擇Keyboard頁簽;(3)在Category框里選擇Macros;(4)在Commands框里,選擇要分配熱鍵的宏;(5)點(diǎn)擊Press new shortcut key框,按下熱鍵,然后點(diǎn)擊Assign按鈕就可以了。

圖3

VC插件 
  前面提到,VBScript宏和VC插件都可以用來擴(kuò)展VC集成開發(fā)環(huán)境的功能,美觀、改造VC的界面,但是它們是有區(qū)別的。主要的區(qū)別當(dāng)然在于:VBScript宏是使用VBScript語言寫的過程,而VC插件則是使用VC或者Visual Basic開發(fā)的COM構(gòu)件。
開發(fā)VBScript宏比開發(fā)插件容易多了。生成一個(gè)VBScript宏只需要記錄宏、增加一些代碼(需要的話),然后運(yùn)行就可以了。而生成一個(gè)插件需要VC來編寫代碼,編譯成DLL,然后與VC的集成開發(fā)環(huán)境連接(安裝插件),才能使用它提供的功能。
VBScript宏在功能上弱于插件。在宏里面,只能夠使用VBScript語言,只能訪問VC集成開發(fā)環(huán)境的對(duì)象;而插件則可以使用更多的語言(VC、VB),不僅能使用VC集成開發(fā)環(huán)境的對(duì)象,還可以使用整個(gè)計(jì)算機(jī)系統(tǒng)的資源。例如,宏里面與用戶交互只能使用VBScript提供的兩個(gè)對(duì)話框InputBox和MsgBox,而插件則可以使用任何形式的對(duì)話框。

  從VBScript宏與插件的這些區(qū)別可以知道:如果使用VBScript宏可以完成的任務(wù),建議盡量使用VBScript宏,因?yàn)殚_發(fā)一個(gè)VBScript宏比開發(fā)一個(gè)插件要簡(jiǎn)單得多、快得多。VC插件更適合于用來提供復(fù)雜的功能,例如:全局查找替換、保存所有的文件并編譯、把VC的窗口變成頁簽式界面(如圖4所示)等等。

圖4

開發(fā)插件的基本步驟如下:
  首先,需要設(shè)計(jì)插件。要確定:插件的功能、是否可以采用VBScript宏來實(shí)現(xiàn)(如果可以,就不開發(fā)這個(gè)插件而選擇宏)、插件提供哪些功能、需要使用哪些集成開發(fā)環(huán)境的對(duì)象、需要使用哪些屬性和方法、需要幾個(gè)插件、是否需要使用對(duì)話框、使用什么對(duì)話框、是否需要使用別的插件、是否需要使用別的應(yīng)用等等。

  其次,需要確定使用什么語言來開發(fā)插件。現(xiàn)在Visual C++、Visual Basic的4.0以上的版本都支持VC插件的開發(fā)。VC專門為插件開發(fā)提供了一個(gè)向?qū)В梢詭湍阃瓿纱蟛糠值墓ぷ鳌H绻褂肰isual Basic的話,則需要使用一些類型庫來訪問VC集成開發(fā)環(huán)境的對(duì)象。因此,建議你使用VC來開發(fā)比較方便。

  接著,需要?jiǎng)?chuàng)建一個(gè)插件的項(xiàng)目。使用VC的插件向?qū)В驅(qū)⒆詣?dòng)創(chuàng)建一個(gè)項(xiàng)目。如果使用VB來開發(fā)插件,最好以一個(gè)例子為基礎(chǔ)。

  項(xiàng)目創(chuàng)建了以后,就需要編寫代碼了。如果使用了VC的插件向?qū)Щ蛘咭訴B的一個(gè)例子為基礎(chǔ)的話,那么大部分代碼已經(jīng)有了,你只需要加入具體處理的一些代碼即可。

  然后,把項(xiàng)目編譯連接成DLL,可以把多個(gè)插件合并在一個(gè)DLL里。最后,在VC里安裝這個(gè)插件就可以使用了。運(yùn)行命令行命令、點(diǎn)擊插件提供的工具條按鈕或者按插件提供的熱鍵就可以使用插件了。

  VC 5.0以上的版本專門為插件的開發(fā)提供了一個(gè)插件向?qū)А?梢允褂眠@個(gè)向?qū)лp松、快速地生成插件的基本代碼,然后根據(jù)自己的需要進(jìn)行修改。使用VC的插件向?qū)нM(jìn)行插件開發(fā)的步驟如下:
首先,設(shè)計(jì)插件。接著,使用插件向?qū)尚碌牟寮?xiàng)目:(1)選擇File菜單的New命令;(2)在New對(duì)話框里,選擇Projects頁簽;(3)在窗口里選擇Developer Studio Add-in Wizard,在Project Name框里填入項(xiàng)目的名字,然后點(diǎn)擊OK;(4)這時(shí)進(jìn)入插件向?qū)?見圖5),為插件填寫名字和描述;如果插件需要工具條按鈕,則選上Provides a toolbar選項(xiàng);如果插件需要處理VC集成開發(fā)環(huán)境對(duì)象的事件,則選上Responds to Developer Studio events選項(xiàng),向?qū)槊總(gè)事件添加一個(gè)代碼框架,你必須為需要的事件提供具體的處理;點(diǎn)擊OK;(5)在彈出的New Project Information對(duì)話框里檢查向?qū)Ъ磳⑸傻奈募绊?xiàng)目目錄,確認(rèn)正確后點(diǎn)擊OK就生成插件項(xiàng)目了。

圖5
然后,定制插件的功能或者增加新的功能。插件向?qū)ё詣?dòng)生成了添加一個(gè)功能到VC集成開發(fā)環(huán)境的代碼,但是如果你需要定制或者添加更多的功能的話,則要修改代碼,這個(gè)與普通應(yīng)用開發(fā)是一樣的。修改需要使用到Application對(duì)象的三個(gè)方法:使用AddCommand方法添加一個(gè)功能;使用AddCommandBarButton方法添加一個(gè)工具條按鈕;使用AddKeyBinding方法來添加一個(gè)熱鍵。具體的做法請(qǐng)參照VC插件開發(fā)的幫助。

  這里需要簡(jiǎn)單說明一下VC集成開發(fā)環(huán)境與插件之間的關(guān)系,如圖6所示。每一個(gè)插件都向外提供了兩個(gè)對(duì)象DSAddIn和Commands。VC的集成開發(fā)環(huán)境使用DSAddIn對(duì)象來裝載或者卸載一個(gè)插件,使用Commands對(duì)象來執(zhí)行插件提供的功能。具體來說,VC是調(diào)用插件的DSAddIn對(duì)象的OnConnection方法來裝載插件的,這個(gè)方法還發(fā)布了插件向外提供的功能接口,如果插件包含了事件的處理,還把連接到VC集成環(huán)境的事件上。VC調(diào)用DSAddIn對(duì)象的OnDisconnection方法來卸載插件。Commands對(duì)象則包含了AddCommand所加入的每一個(gè)功能接口,編寫插件的時(shí)候必須為每一個(gè)功能接口編寫代碼。

圖6

  最后,把插件編譯連接成DLL。安裝插件的方法是:(1)選擇Tools菜單的Customize命令;(2)選擇Add-ins and Macro Files頁簽,如果插件的名字沒有出現(xiàn)在窗口里,則點(diǎn)擊Browse按鈕去定位。(3)在窗口里打勾選上需要安裝的插件即可;如果取消選擇某個(gè)插件,則會(huì)卸載這個(gè)插件。插件安裝了以后,VC每次啟動(dòng)都會(huì)自動(dòng)裝載這個(gè)插件,你就可以使用這個(gè)插件提供的功能來為自己的應(yīng)用開發(fā)服務(wù)了。

]]>
Unix/Linux下C/C++開發(fā)技術(shù)概覽http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2434&Page=1wangxinxin2010-12-10 15:03:09Windows和Unix是當(dāng)前兩大主流操作系統(tǒng)平臺(tái),基于C/C++的開發(fā)人員經(jīng)常會(huì)面臨這兩個(gè)平臺(tái)之間的移植的問題。Unix作為一個(gè)開發(fā)式的系統(tǒng),其下有出現(xiàn)了很多個(gè)分支,包括Sun的Solaris、IBM的AIX、HP Unix、SCO Unix、Free BSD、蘋果的MAC OS以及開源的Linux等。對(duì)于這些Unix的分支操作系統(tǒng),其實(shí)現(xiàn)又有很大的差別,因此開發(fā)人員又要針對(duì)這些不同的系統(tǒng)進(jìn)行移植。本文的目的就是介紹一下Windows平臺(tái)和Unix平臺(tái)之間的差別,并簡(jiǎn)單介紹一下不同Unix分支操作系統(tǒng)之間的差別,在移植開發(fā)過程中的一些注意事項(xiàng),同時(shí)簡(jiǎn)要介紹一下Unix下開發(fā)的一般流程和常用的開發(fā)調(diào)試工具。

關(guān)于平臺(tái)之間的差異,主要是Windows平臺(tái)和Unix平臺(tái)之間的差異,這里著重介紹一下這兩個(gè)平臺(tái)在C/C++開發(fā)中存在的差異,其間會(huì)穿插介紹一些Unix不同分支之間的差異。

1.1語言特性的差異

       語言特性的差異,指的是不同操作系統(tǒng)平臺(tái)中,實(shí)現(xiàn)C++/C時(shí)的一些細(xì)微的差異,忽略這些差異可能會(huì)帶來一些特別隱蔽的錯(cuò)誤。而且可能是致命的錯(cuò)誤。所以,了解語言特性的差異,對(duì)于在Unix移植來說非常重要。如果考慮系統(tǒng)多多個(gè)平臺(tái)支持,就必須了解在不同平臺(tái)下語言特性的差異,從開發(fā)一開始就把這些因素考慮進(jìn)去,這樣才能最低限度的降低移植的過程中工作量。

1.1.1字節(jié)順序的差異

       字節(jié)順序指的主要是整型變量在內(nèi)存中的存儲(chǔ)方式。在計(jì)算機(jī)中,數(shù)據(jù)都是以二進(jìn)制方式存儲(chǔ)的,包括在內(nèi)存和硬盤中。而計(jì)算機(jī)又以8位二進(jìn)制作為一個(gè)存儲(chǔ)單元。在32位系統(tǒng)中,一個(gè)整型的存儲(chǔ)需要四個(gè)存儲(chǔ)單元。也就是說要把一個(gè)32位的整數(shù)分割成位四段分別進(jìn)行存儲(chǔ),而每一段的存儲(chǔ)位置就是字節(jié)順序的差異。為了清楚的表示每段存儲(chǔ)的先后位置,我們用16進(jìn)制來表示一段的值,下表列出了在Unix系統(tǒng)和Windows系統(tǒng)中整數(shù)20000在內(nèi)存中的情況。

十六進(jìn)制表示

0x00004E20

Windows內(nèi)存表示

20 4E 00 00

Unix內(nèi)存表示

00 00 4E 20

如表中所示,Windows中存儲(chǔ)方式和該整數(shù)的16進(jìn)制表示是相反,是一種低位在前高位在后的存儲(chǔ)順序。而Unix下的存儲(chǔ)順序和正常的16進(jìn)制表示的順序相同,稱為高位在前低位在后的順序。這種差異帶來的問題,主要體現(xiàn)在以下幾個(gè)方面:

?         網(wǎng)絡(luò)通信時(shí)

當(dāng)Windows和Unix之間發(fā)生網(wǎng)絡(luò)數(shù)據(jù)傳輸,傳輸一個(gè)整型數(shù)據(jù)(如一個(gè)數(shù)據(jù)包的長(zhǎng)度)的時(shí)候,如果不經(jīng)處理直接把內(nèi)存中的數(shù)據(jù)傳輸過去,那么在對(duì)方看來完全是另一個(gè)數(shù)據(jù),這樣就會(huì)造成問題。如Windows下面發(fā)送過去一個(gè)20000(0x00004E20),在Unix下面收到的數(shù)據(jù)就會(huì)被理解成541982720(0x204E0000),這簡(jiǎn)直是天壤之別。

?         文件存儲(chǔ)和讀取時(shí)

跟網(wǎng)絡(luò)傳輸類似,如果在Windows下面把某個(gè)整數(shù)寫到了文件中,然后在Unix下面打開這個(gè)文件讀取該數(shù)據(jù),就會(huì)出現(xiàn)跟上面類似的問題。

       這個(gè)問題主要體現(xiàn)在不同平臺(tái)之間互操作時(shí),在多平臺(tái)開發(fā)過程中,尤其時(shí)在網(wǎng)絡(luò)應(yīng)用開發(fā)的時(shí)候,兩個(gè)平臺(tái)之間數(shù)據(jù)交互是非常普遍的,所以這個(gè)問題也就顯的很普遍。解決這個(gè)問題的方法就是交互的雙方采用一種相同的數(shù)據(jù)編碼標(biāo)準(zhǔn),就是數(shù)據(jù)在傳輸和存儲(chǔ)的時(shí)候采用什么方法進(jìn)行編碼,具體的做法有一下幾種:

1.  數(shù)字轉(zhuǎn)換成字符傳進(jìn)行交互

2.  協(xié)商一個(gè)同意的字節(jié)順序,根據(jù)自己平臺(tái)的字節(jié)順序還原數(shù)據(jù)

3.  采用其他標(biāo)準(zhǔn)的編碼方式,如ASN1編碼


跟這個(gè)問題類似,32位系統(tǒng)和64位系統(tǒng)的差異也會(huì)出現(xiàn)這樣的問題,解決方法跟這個(gè)問題的解決方法相同。在32位系統(tǒng)和64位系統(tǒng)中,長(zhǎng)整型(long)分別用32位和64位表示,這樣,在不同系統(tǒng)之間交互的時(shí)候必然會(huì)出現(xiàn)整型數(shù)據(jù)表示方式不同的問題。目前大多數(shù)Windows系統(tǒng)都是32位的系統(tǒng),而Unix中很多都是64位的,尤其是大型的服務(wù)器,所以這個(gè)問題必須引起重視。

1.1.2變量的作用域差異

在不同的系統(tǒng)下,由于編譯器的不同,對(duì)變量作用域的實(shí)現(xiàn)機(jī)制也有所不同,這里以Windows下的VC和Solaris下的CC這兩個(gè)編譯器為例做一個(gè)簡(jiǎn)單的比較說明。

在C++的開發(fā)過程中,我們經(jīng)常會(huì)有這樣的用法:

       for(int i=0;i<num;i++)

       {

              …

       }

這是一種最常用的for循環(huán)的用法,因?yàn)槠渲衖主要使用來控制循環(huán),所以一般沒有必要拿出來單獨(dú)進(jìn)行聲明,只是放在for語句中一起聲明。這里i、j等簡(jiǎn)單的變量就成了我們常用的變量,一般不按照編程規(guī)范那樣為他們命名。就是這種聲明方法,在Windows下和Solaris下有了不同的理解,i的作用域不同。我們先把作用域進(jìn)行劃分,如下:

       {

              …

              for(int i=0;i<num;i++)

II

              {

I

                     …

              }

              …

              …

       }


我們劃分出I和II兩個(gè)作用域,其中作用域II包含在作用域I當(dāng)中。在Windows下,變量i的作用域是I的整個(gè)范圍,而Solaris下的i的作用域只是II的范圍。其實(shí)標(biāo)準(zhǔn)的C++語法應(yīng)該是Solaris的做法,但是微軟在實(shí)現(xiàn)的時(shí)候沒有按照這個(gè)標(biāo)準(zhǔn)實(shí)現(xiàn),這就引發(fā)了我們討論的這個(gè)問題。由于這個(gè)差異,就引發(fā)了一些微妙而隱蔽的問題。先看一下下面兩端代碼。

A:

       for(int i=0;i<num;i++)

       {

              …

       }

       …

       for(i=0;i<num;i++)

       {

              …

       }


B:

       for(int i=0;i<num;i++)

       {

              …

       }

       …

       for(int i=0;i<num;i++)

       {

              …

       }


代碼A在Windows下面可以正常編譯,而在Solaris下面確編不過去,提示第二個(gè)for循環(huán)中變量i沒有定義。相反代碼B在Solaris下可以正常編譯,而在Windows下面編不過去,提示第二個(gè)for循環(huán)中變量i重復(fù)定義。

在通常的情況下,我們會(huì)按照B的方法書寫代碼,而在Windows編譯是出現(xiàn)錯(cuò)誤,然后改成A的那種形式。這樣,在Windows下就沒有問題了,程序也可以編譯過去了,但是到Solaris下時(shí),有會(huì)出現(xiàn)問題,這是就不得不把i的聲明拿到所有for循環(huán)的外面。當(dāng)i的聲明拿到for循環(huán)的外面時(shí),真正的問題來了。首先提示一下,這樣的一段代碼是沒有問題的:

C:

int i = 0;

if(cond)

{

       …

       for(int i=0;i<num;i++)

       {

              …

       }

       …

}

       這是一段正確的代碼,雖然在外面已經(jīng)定義了i,但是在for里面重新定義一個(gè)i也沒有問題,這是C++的語法所允許的(java里面不允許這樣做)。但就是因?yàn)檫@種C++語言的靈活機(jī)制,引發(fā)了問題的產(chǎn)生。

       問題產(chǎn)生源于程序中出現(xiàn)了A_B那樣的代碼,然后把i的聲明拿到了外面。在后期維護(hù)的過程中,又在后面增加了一個(gè)循環(huán),但是卻是按照C的那種方式增加的,這樣就產(chǎn)生了問題。請(qǐng)看如下代碼:

       int i=0;

       char str1[10];

       char str2[10];

       strcpy(str1,”hello”);

       …

       for(i=0;i<20;i++)

       {

              …

I

       }

       …

       if(cond)

       {

              for(int i=0;i<10;i++)

III

              {

II

                     if(str1[i]==0)  break;

              }

              memcpy(str2,str1,i);

              str2[i]=0;

       }

       …


在上述代碼,為了分析方便,我們把整段代碼分成I、II和III三個(gè)作用域。其中作用域II就是整個(gè)if語句,實(shí)現(xiàn)的相當(dāng)于一個(gè)strcpy函數(shù)的功能。II中的內(nèi)容就好是我們上面說的后期維護(hù)中加入的,當(dāng)然,實(shí)際情況并不像我們例子中這么明前,i的聲明可能離我們的if語句很遠(yuǎn),所以加入這段代碼是不知道上面是否聲明了i變量。而且,這段代碼編譯的時(shí)候也不回出錯(cuò),不管是Windows還是Solaris(單獨(dú)的一段II中的代碼在Solaris下面編不過去)。在Windows下面,這段代碼可以正常的運(yùn)行,不回出現(xiàn)任何問題,因?yàn)镮I中的代碼完全是根據(jù)Windows下的習(xí)慣編寫的。但是在Solaris下面,這段代碼就會(huì)出現(xiàn)內(nèi)存越界的錯(cuò)誤,雖然編譯可以正常通過,但是實(shí)現(xiàn)的卻不是程序員預(yù)期的目的。在執(zhí)行memcpy的時(shí)候,那個(gè)i其實(shí)是外層聲明的那個(gè)i,值是20,而str2和str1的大小之后10,所以就發(fā)生了讀寫內(nèi)存越界。而程序員預(yù)想的,這個(gè)i是for循環(huán)算出來的str1字符串的長(zhǎng)度,應(yīng)該是5。

要解決這類問題,就得加強(qiáng)編程規(guī)范,杜絕這種錯(cuò)誤代碼的生成。從開始的時(shí)候就要意識(shí)到可能產(chǎn)生的問題,從而避免問題的發(fā)生。

]]>
VC++/MFC(VC6)開發(fā)技術(shù)精品學(xué)習(xí)資料下載匯總http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2433&Page=1wangxinxin2010-12-10 15:00:50
以下內(nèi)容含腳本,或可能導(dǎo)致頁面不正常的代碼
說明:上面顯示的是代碼內(nèi)容。您可以先檢查過代碼沒問題,或修改之后再運(yùn)行.
]]>
任務(wù)腳本Python語言教程http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2432&Page=1wangxinxin2010-12-10 14:51:48 J2Y S+%K  
簡(jiǎn)介: LeEv']  
crvq]J5  
Python是一種簡(jiǎn)單易學(xué),功能強(qiáng)大的編程語言,它有高效率的高層數(shù)據(jù)結(jié)構(gòu),簡(jiǎn)單而有效地實(shí)現(xiàn)面向?qū)ο缶幊獭ython簡(jiǎn)潔的語法和對(duì)動(dòng)態(tài)輸入的支持,再加上解釋性語言的本質(zhì),使得它在大多數(shù)平臺(tái)上的許多領(lǐng)域都是一個(gè)理想的腳本語言,特別適用于快速的應(yīng)用程序開發(fā)。 Ng,< 4;  
@a~GHG[x  
Python的特色: )y#~eYn  
QJ%[6S  
簡(jiǎn)單 &\p=s.y?j  
Python是一種代表簡(jiǎn)單主義思想的語言。閱讀一個(gè)良好的Python程序就感覺像是在讀英語一樣,盡管這個(gè)英語的要求非常嚴(yán)格!Python的這種偽代碼本質(zhì)是它最大的優(yōu)點(diǎn)之一。它使你能夠?qū)W⒂诮鉀Q問題而不是去搞明白語言本身。 pVN) k  
^.?5!9U  
易學(xué) Gm1[PAj  
就如同你即將看到的一樣,Python極其容易上手。前面已經(jīng)提到了,Python有極其簡(jiǎn)單的語法。 _(zPA4q8q  
ZIr&_x#e  
免費(fèi)、開源 K. l7yBm  
Python是FLOSS(自由/開放源碼軟件)之一。簡(jiǎn)單地說,你可以自由地發(fā)布這個(gè)軟件的拷貝、閱讀它的源代碼、對(duì)它做改動(dòng)、把它的一部分用于新的自由軟件中。FLOSS是基于一個(gè)團(tuán)體分享知識(shí)的概念。這是為什么Python如此優(yōu)秀的原因之一——它是由一群希望看到一個(gè)更加優(yōu)秀的Python的人創(chuàng)造并經(jīng)常改進(jìn)著的。 _VM()n;  
*wu:fb2[(  
高層語言 ?ypX``3#s7  
當(dāng)你用Python語言編寫程序的時(shí)候,你無需考慮諸如如何管理你的程序使用的內(nèi)存一類的底層細(xì)節(jié)。 PgMU|O7To  
}Kt1mmo:`  
可移植性 tX'2 $}  
由于它的開源本質(zhì),Python已經(jīng)被移植在許多平臺(tái)上(經(jīng)過改動(dòng)使它能夠工作在不同平臺(tái)上)。如果你小心地避免使用依賴于系統(tǒng)的特性,那么你的所有Python程序無需修改就可以在下述任何平臺(tái)上面運(yùn)行。 8?z7!k]  
g*-%.fNA  
這些平臺(tái)包括Linux、Windows、FreeBSD、Macintosh、Solaris、OS/2、Amiga、AROS、AS/400、BeOS、OS/390、z/OS、Palm OS、QNX、VMS、Psion、Acom RISC OS、VxWorks、PlayStation、Sharp Zaurus、Windows CE甚至還有PocketPC! appWq}db  
2M$^|j:[  
解釋性 29tih{ xx  
這一點(diǎn)需要一些解釋。 C;jV)hr6P  
~M Mv+d88  
一個(gè)用編譯性語言比如C或C++寫的程序可以從源文件(即C或C++語言)轉(zhuǎn)換到一個(gè)你的計(jì)算機(jī)使用的語言(二進(jìn)制代碼,即0和1)。這個(gè)過程通過編譯器和不同的標(biāo)記、選項(xiàng)完成。當(dāng)你運(yùn)行你的程序的時(shí)候,連接/轉(zhuǎn)載器軟件把你的程序從硬盤復(fù)制到內(nèi)存中并且運(yùn)行。 Ef2i#BoZ  
/kH 7I  
而Python語言寫的程序不需要編譯成二進(jìn)制代碼。你可以直接從源代碼 運(yùn)行 程序。在計(jì)算機(jī)內(nèi)部,Python解釋器把源代碼轉(zhuǎn)換成稱為字節(jié)碼的中間形式,然后再把它翻譯成計(jì)算機(jī)使用的機(jī)器語言并運(yùn)行。事實(shí)上,由于你不再需要擔(dān)心如何編譯程序,如何確保連接轉(zhuǎn)載正確的庫等等,所有這一切使得使用Python更加簡(jiǎn)單。由于你只需要把你的Python程序拷貝到另外一臺(tái)計(jì)算機(jī)上,它就可以工作了,這也使得你的Python程序更加易于移植。 /+JHnedK  
~/l5ys  
面向?qū)ο?`JzP V/6  
Python即支持面向過程的編程也支持面向?qū)ο蟮木幊獭T?面向過程 的語言中,程序是由過程或僅僅是可重用代碼的函數(shù)構(gòu)建起來的。在 面向?qū)ο?的語言中,程序是由數(shù)據(jù)和功能組合而成的對(duì)象構(gòu)建起來的。與其他主要的語言如C++和Java相比,Python以一種非常強(qiáng)大又簡(jiǎn)單的方式實(shí)現(xiàn)面向?qū)ο缶幊獭?span style="DISPLAY: none"> q .s'z}  
kkU#0p?7  
可擴(kuò)展性 %*a%F~Ss  
如果你需要你的一段關(guān)鍵代碼運(yùn)行得更快或者希望某些算法不公開,你可以把你的部分程序用C或C++編寫,然后在你的Python程序中使用它們。 7 ?"-:q  
)z!#8s  
可嵌入性 'BX U '  
你可以把Python嵌入你的C/C++程序,從而向你的程序用戶提供腳本功能。 .kc{)d*0K  
 N~vK8j@  
豐富的庫 ^KUM4. 6  
Python標(biāo)準(zhǔn)庫確實(shí)很龐大。它可以幫助你處理各種工作,包括正則表達(dá)式、文檔生成、單元測(cè)試、線程、數(shù)據(jù)庫、網(wǎng)頁瀏覽器、CGI、FTP、電子郵件、XML、XML-RPC、HTML、WAV文件、密碼系統(tǒng)、GUI(圖形用戶界面)、Tk和其他與系統(tǒng)有關(guān)的操作。記住,只要安裝了Python,所有這些功能都是可用的。這被稱作Python的“功能齊全”理睢?  Q5 =  
除了標(biāo)準(zhǔn)庫醞猬還有許多其他高質(zhì)量的庫,如wxPython、Twisted和Python圖像庫等等。 oD 3Q{ e  
;nw}x4Y[  
~F 13}is  
                            第二部分  安裝編譯環(huán)境 Lm7fz9F%  
:Fdk`aC  
Xp~O?2:3l  
注:由于linux系統(tǒng)本身都集成Python,本部分主要針對(duì)windows的調(diào)試環(huán)境 ]~7xq)28  
(``|5;T\  
可以從www.Python.org/download下載到。安裝過程與其他Windows軟件類似。 X;d 1@ G  
+?+iVLr!l}  
提示 4_w{~  
即便安裝程序?yàn)槟闾峁┝瞬粰z查 可選 組件的選項(xiàng),你也不要不作任何檢查!有些組件對(duì)你很有用,特別是集成開發(fā)環(huán)境。 %$=}ePD  
U}SN#[*  
在Windows命令行中使用Python M (.Up  
如果你想要從Windows命令行調(diào)用Python,那么你需要先正確的設(shè)置PATH變量。 3/*<i  
B8 R&Q8Q  
對(duì)于Windows 2000、XP、2003,點(diǎn)擊控制面板->系統(tǒng)->高級(jí)->環(huán)境變量。在“系統(tǒng)變量”表單中點(diǎn)擊叫做PATH的變量,然后編輯這個(gè)變量,把;C:\Python23加到它的結(jié)尾。當(dāng)然,是Python所在的正確目錄名。 .h\[7r  
%$zX a%A  
U[c^xz&  
                        第三部分  Hello World UYsyVY`Fm|  
9Xeg &Z|!  
對(duì)于Windows用戶,只要你正確的設(shè)置了PATH變量,你應(yīng)該可以從命令行啟動(dòng)解釋器。或者你可以選擇使用IDLE程序。IDLE是集成開發(fā)環(huán)境的縮寫。點(diǎn)擊開始->程序->Python 2.3->IDLE(Python GUI)。Linux用戶也可以使用IDLE。 Un{9reX5  
K) {\wV="  
注意,>>>是你鍵入Python語句的提示符。 afj[HJbY  
F!~oJ  
guk Ka  
$ python -+Ab[  
Python 2.3.4 (#1, Oct 26 2004, 16:42:40) dEWI8Q]  
[GCC 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)] on linux2 Q:sw*7"F  
Type "help", "copyright", "credits" or "license" for more information. 2N[S*#~*e  
>>> print 'hello world' 'n0u6hCSb  
hello world t&L+]I'P3  
>>> L>1i~c&V  
v35=4>Y  
注意,Python會(huì)在下一行立即給出你輸出!你剛才鍵入的是一句Python 語句 。我們使用print(不要驚訝)來打印你提供給它的值。這里,我們提供的是文本Hello World,它被迅速地打印在屏幕上。 gdkQ h_\  
_"R /k`8  
如何退出Python提示符 5$.e5y<&(  
如果你使用的是Linux/BSD shell,那么按Ctrl-d退出提示符。如果是在Windows命令行中,則按Ctrl-z再按Enter。 I# U"DwM  
/3ty*LQT  
WfF~\DlrD  
                          第四部分  選一個(gè)編輯器 s 8 c#_  
krI@N}OU  
'ZboLoS*-  
在我們開始講述以源文件方式編寫Python程序之前,我們需要一個(gè)編輯器來寫源文件。挑選一個(gè)編輯器確實(shí)是極其重要的。你挑選一個(gè)編輯器就如同你挑選一輛你將購買的轎車一樣。一個(gè)好的編輯器會(huì)幫助你方便地編寫Python程序,使你地編程旅程更加舒適,幫助你更加快捷安全地到達(dá)目的地(實(shí)現(xiàn)目標(biāo))。 AYnk.H-v  
8M&q  
對(duì)于編輯器的基本要求之一是語法加亮功能,利用這一功能,你的Python程序的不同部分被標(biāo)以不同的顏色,這樣你可以更好 看清楚 你的程序,使它的運(yùn)行顯得形象化。 Ns} BE H  
d=v{3*a_4,  
如果你使用Windows,那么我建議你使用IDLE。IDLE具備語法加亮功能,還有許多其他的功能,比如允許你在IDLE中運(yùn)行你的程序。特別值得注意的是:不要使用Notepad——它是一個(gè)糟糕的選擇,因?yàn)樗鼪]有語法加亮功能,而且更加重要的是,它不支持文本縮進(jìn)。而我們將會(huì)看到文本縮進(jìn)對(duì)于我們來說極其重要。一個(gè)好的編輯器,比如IDLE(還有VIM)將會(huì)自動(dòng)幫助你做這些事情。 PZjK 6]N\  
S_ELV#X  
如果你使用Linux/FreeBSD,那么你有很多種選擇。如果你是一位有經(jīng)驗(yàn)的程序員,你一定已經(jīng)在使用VIM或者Emacs了。勿庸置疑,它們是兩個(gè)功能最強(qiáng)大的編輯器。使用它們編寫你的Python程序,你將從中受益。我個(gè)人使用VIM編寫我的大多數(shù)程序。如果你是一個(gè)初學(xué)編程的人,那么你可以使用Kate,它也是我最喜歡的編輯器之一。只要你愿意花時(shí)間學(xué)習(xí)使用VIM或Emacs,那么我強(qiáng)烈建議你一定要學(xué)習(xí)兩者之一,因?yàn)閺拈L(zhǎng)遠(yuǎn)看來它們對(duì)你是極其有幫助的。 Un.u{$po  
A<$w }Fy;  
如果你還想尋找一下其他可供選擇的編輯器,可以看一下詳盡的Python編輯器列表,然后作出你的選擇。你也可以使用Python的IDE(集成開發(fā)環(huán)境)。請(qǐng)看一下詳盡的支持Python的IDE列表以獲得詳盡的信息。一旦你開始編寫大型的Python程序,IDE確實(shí)很有用。 |_GESpoHH  
$(=0J*ND"  
我再一次重申,請(qǐng)選擇一個(gè)合適的編輯器——它能使編寫Python程序變得更加有趣、方便。 s-"oT=  
aSVR +of  
注:我們寫L2J任務(wù)腳本用windows記事本即可 4;D>s8dgG  
=`W#R  
r0L' mf$  
746['sf4c  
                      第五部分  源文件編譯 /)/>/4O  
`Dp_c&9]  
>m'n#=yap  
使用源文件 r[W Ir|r7  
現(xiàn)在讓我們重新開始編程。當(dāng)你學(xué)習(xí)一種新的編程語言的時(shí)候,你編寫運(yùn)行的第一個(gè)程序通常都是“Hello World”程序,這已經(jīng)成為一種傳統(tǒng)了。在你運(yùn)行“Hello World”程序的時(shí)候,它所做的事只是說聲:“Hello World”。正如提出“Hello World”程序的Simon Cozens[1]所說:“它是編程之神的傳統(tǒng)咒語,可以幫助你更好的學(xué)習(xí)語言。” rcU*6`IWA  
v FW g0 $,  
啟動(dòng)你選擇的編輯器,輸入下面這段程序,然后把它保存為helloworld.py。 w6<zPrA  
.F^372hH3  
例3.2 使用源文件 _]6n]koD,  
H%G|8,4  
#!/usr/bin/python =niT]xf  
# Filename : helloworld.py o3,}X@p  
print 'Hello World' tr@)zM GB  
7;3;8Q FX  
(源文件:code/helloworld.py) Sgq" 3(+%,  
{vox x&UX  
為了運(yùn)行這個(gè)程序,請(qǐng)打開shell(Linux終端或者DOS提示符),然后鍵入命令python helloworld.py。如果你使用IDLE,請(qǐng)使用菜單Edit->Run Script或者使用鍵盤快捷方式Ctrl-F5。輸出如下所示。 |<!xD iB  
|{9&!=/qf  
輸出 4`'V%)M  
$ python helloworld.py O~4Q:#^c  
Hello World OCv,EZ  
Rgb&EnVW  
如果你得到的輸出與上面所示的一樣,那么恭喜!——你已經(jīng)成功地運(yùn)行了你的第一個(gè)Python程序。 fR#W#n#m  
L!0}&i;u~5  
萬一你得到一個(gè)錯(cuò)誤,那么請(qǐng)確保你鍵入的程序 準(zhǔn)確無誤 ,然后再運(yùn)行一下程序。注意Python是大小寫敏感的,即print與Print不一樣——注意前一個(gè)是小寫p而后一個(gè)是大寫P。另外,確保在每一行的開始字符前沒有空格或者制表符——我們將在后面討論為什么這點(diǎn)是重要的。 Iwe  
>/G[Oo  
它如何工作 Xh@;4n  
讓我們思考一下這個(gè)程序的前兩行。它們被稱作 注釋 ——任何在#符號(hào)右面的內(nèi)容都是注釋。注釋主要作為提供給程序讀者的筆記。 1^tM%2rP'  
Xa_:B\ic  
Python至少應(yīng)當(dāng)有第一行那樣的特殊形式的注釋。它被稱作 組織行 ——源文件的頭兩個(gè)字符是#!,后面跟著一個(gè)程序。這行告訴你的Linux/Unix系統(tǒng)當(dāng)你 執(zhí)行 你的程序的時(shí)候,它應(yīng)該運(yùn)行哪個(gè)解釋器。這會(huì)在下一節(jié)做詳細(xì)解釋。注意,你總是可以通過直接在命令行指定解釋器,從而在任何平臺(tái)上運(yùn)行你的程序。就如同命令python helloworld.py一樣。 h(p c GE  
uoTc c|Kc  
重要 E&>;a!0b]  
在你的程序中合理地使用注釋以解釋一些重要的細(xì)節(jié)——這將有助于你的程序的讀者輕松地理解程序在干什么。記住,這個(gè)讀者可能就是6個(gè)月以后的你! W4"1H0s`l  
 {EJ+   
跟在注釋之后的是一句Python 語句 ——它只是打印文本“Hello World”。print實(shí)際上是一個(gè)操作符,而“Hello World”被稱為一個(gè)字符串——?jiǎng)e擔(dān)心我們會(huì)在后面詳細(xì)解釋這些術(shù)語]]>
C++附帶的C語言運(yùn)行時(shí)庫http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2431&Page=1wangxinxin2010-12-10 14:50:17第一部分:基礎(chǔ)

 

微軟在其Visual C++產(chǎn)品中包含了一套C語言運(yùn)行時(shí)庫,它的其它庫產(chǎn)品大多基于這一套庫(比如MFC)。在特殊的場(chǎng)合,我們可能需要使用自己的運(yùn)行時(shí)庫來替代它。比如,某一些對(duì)于注重系統(tǒng)綜合性能的游戲。那時(shí),我們只需要實(shí)現(xiàn)運(yùn)行時(shí)庫中的某一些功能,甚至可以不按照標(biāo)準(zhǔn)來命名(因?yàn)槟鞘悄阕约旱倪\(yùn)行庫,并且你不打算發(fā)布她)。比方說C語言運(yùn)行時(shí)的內(nèi)存分配函數(shù),常用的不外乎malloccallocfreerealloc這幾個(gè),我們實(shí)現(xiàn)的時(shí)候就沒有必要遵照以上的名字命名我們的相應(yīng)功能的函數(shù)。

在替代運(yùn)行庫以前必須認(rèn)識(shí)到的是,許多基于運(yùn)行庫的函數(shù)庫將不能再使用,比如剛才提到的(MFC)庫,而你在以前編寫的許多庫可能不能再使用,這意味著你可能要白手起家。(需要說明的是:ATL庫基本沒有使用C語言運(yùn)行時(shí)庫,所以可以繼續(xù)使用,前提是使用時(shí)不要連接MFC)。

 

 

1.    基本概念

我們平時(shí)接觸VC++的時(shí)候,第一個(gè)接觸到的恐怕是WinMainmain,對(duì)應(yīng)于Win32子系統(tǒng)的Windows窗口系統(tǒng)和控制臺(tái)兩個(gè)部分,最多是某些書籍上談到了對(duì)應(yīng)多字節(jié)字符集的幾個(gè)變種。其實(shí),這幾個(gè)入口點(diǎn)函數(shù)是VC++帶有的C運(yùn)行庫要求的入口點(diǎn)。真正的vc程序的入口點(diǎn)函數(shù)是在使用VC++C編譯器編譯程序時(shí)指定的。它可以是符合下面形式的任何名稱的函數(shù):

void __cdecl Your_Entry (void);

如果你喜歡,你可以起一個(gè)更加藝術(shù)的名字。

說到這里,給出一個(gè)樣例程序可以更好的理解這個(gè)入口點(diǎn)函數(shù)和我們平時(shí)接觸的C運(yùn)行時(shí)入口點(diǎn)函數(shù)之間有些什么。這是一個(gè)什么都不做的程序

 

// VC++ Entry point

void MyEntry (void);

{

{

 

將這些個(gè)字符敲在一個(gè)文本文件中,保存為:d:\test0.c

 

然后在VC++命令提示符環(huán)境中鍵入下面的步驟來編譯、連接這個(gè)程序(在上一個(gè)版本中,我把這個(gè)部分漏了,這可能使得不少人看了這篇文章卻不知道如何實(shí)現(xiàn)):

l         進(jìn)入VC++bin目錄,缺省安裝下,它應(yīng)該在如下的目錄中:

C:\Program files\Microsoft Visual Studio\VC98\Bin

然后運(yùn)行vcvars32.bat批處理文件,如下圖所示:

注意:我的機(jī)子上的目錄可能和你的不一樣。

 

屏幕會(huì)提示順利設(shè)置了vc的環(huán)境變量。

 

l         然后用下面的命令編譯上面的代碼文件

d:\

cl /c test0.c /nologo

如果沒有什么提示而很快的出現(xiàn)命令提示符,則表示編譯成功。

l         然后用下面的命令連接

link /ENTRY:”MyEntry” /OUT:test0.exe /SUBSYSTEM:WINDOWS /NODEFAULTLIB test0.obj /nologo

不出什么意外的話,在D分區(qū)上應(yīng)該有一個(gè)test0.exe文件,雙擊它發(fā)現(xiàn)什么也沒有出現(xiàn)。但是,其實(shí)它是一個(gè)不折不扣的Win32應(yīng)用程序。你可以用相應(yīng)工具來測(cè)試它,可以發(fā)現(xiàn)在入口點(diǎn)處是幾個(gè)符合C函數(shù)調(diào)用規(guī)則的幾個(gè)壓棧、數(shù)據(jù)轉(zhuǎn)移、和出棧指令。

上面用到的一些cllink程序開關(guān)選項(xiàng)的意義請(qǐng)參考MSDN

 

值得提一提的是:缺省情況下,link程序連接了4個(gè)C運(yùn)行時(shí)庫中的某一個(gè),并且將函數(shù)mainCRTStartupwmainCRTStartupWinMainCRTStartupwWinMainCRTStartup中的一個(gè)作為缺省的入口點(diǎn)(我們這里只討論非動(dòng)態(tài)連接庫,也就是一般的可執(zhí)行印象)。具體使用哪個(gè),是根據(jù)link命令行中指定的子系統(tǒng)。可以參考MSDN獲取更詳細(xì)的說明。

 

2.    Microsoft C/C++ Runtime Library

有了上面這些基礎(chǔ),我們接著再看一看Microsoft C/C++ Runtime Library在入口點(diǎn)處都作了些什么。我這里給出的代碼是經(jīng)過篩選的,只是為了說明問題,這些代碼在VC安裝目錄中CRT\SRC下面的crt0.c中,缺省沒有安裝。

 

#undef _UNCODE

void WinMainCRTStartup (void)

{

int mainret;

 

STARTUPINFO StartupInfo;

_osver = GetVersion ();

 

_winminor = (osver >>8) & 0x00FF;

_winmajor = _osver & 0x00FF;

_winver = (winmajor << 8) + _winminor;

osver = (osver >> 16) & 0x00FFFF;

 

if (!_heap_init (1))

fast_error_exit (_RT_HEAPINIT);

 

_acmdln = (char*) GetCommandLineA ();

_aenvptr = (char*) __crtGetEnvironmentStringsA ();

_setargv ();

_setenvp ();

 

_cinit ();

 

StartupInfo.dwFlags = 0;

GetStartupInfo (&StartupInfo);

 

mainret = WinMain (GetModuleHandleA (NULL),

NULL,

;pszCommandLine,

StartupInfo.dwFlags & STARTF_USESHOWWINDOWS ?

StartupInfo.wShowWindow : SW_SHOWDEFAULT);

 

exit (mainret);

}

 

上面的代碼經(jīng)過篩選,它用于多線程下,普通的多字符集C運(yùn)行時(shí)。我稍微解釋一下代碼的含義,它完成以下任務(wù):

l         獲取操作系統(tǒng)的版本信息,用于以后的操作;

l         然后初始化進(jìn)程堆棧;

l         獲取命令行,獲取和設(shè)置環(huán)境變量;

l         C運(yùn)行時(shí)內(nèi)部變量的初始化;

l         調(diào)用標(biāo)準(zhǔn)Win32窗口程序入口點(diǎn)函數(shù)(它應(yīng)該是在你的應(yīng)用程序中被定義和實(shí)現(xiàn)的);

l         調(diào)用ExitProcess函數(shù)退出應(yīng)用程序,退出代碼是WinMain的返回值。

具體的代碼請(qǐng)參見運(yùn)行庫的源代碼。

 

3.    不使用運(yùn)行庫編寫自己的應(yīng)用邏輯

接著,我們來試試看,不使用C運(yùn)行庫,并且使得我們的應(yīng)用程序做些個(gè)事情。請(qǐng)看下面的代碼:

 

// 程序init.c

#pragma once

#include <windows.h>

 

void entry (void)

{

       char** p;

       char* pAlloc;

 

       char* pszNames[] = {

              "SNK",

              "Capcom",

              "Nintindo",

              "EA",

              "3DO",

              NULL

       };

 

       for (p = pszNames; *p != NULL; p ++)

       {

              MessageBox (0, *p, 0, MB_OK);

       }

 

       pAlloc = VirtualAlloc (0, 4096, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);

       if (pAlloc)

       {

              const char* pText = "Hello, world!";

              char* pTemp = (char*) pText, *pstr = pAlloc;

              for (;*pTemp != '\0';) *pstr++ = *pTemp++;

              *pstr = *pTemp;

              MessageBox (0, pAlloc, 0, MB_OK);

              VirtualFree (pAlloc, 4096, MEM_RELEASE);

       }

}

 

使用下面的命令行來編譯連接它

cl init.c /c

link init.obj /SUBSYSTEM:WINDOWS /OUT:init.exe /ENTRY:”entry” /NODEFAULTLIB kernel32.lib user32.lib

生成的init.exe程序的運(yùn)行中界面如下:

                          

]]>
給粗心的C語言初學(xué)者(1)http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2430&Page=1wangxinxin2010-12-10 14:48:11
0 簡(jiǎn)介

C語言及其典型實(shí)現(xiàn)被設(shè)計(jì)為能被專家們?nèi)菀椎厥褂谩_@門語言簡(jiǎn)潔并附有表達(dá)力。但有一些限制可以保護(hù)那些浮躁的人。一個(gè)浮躁的人可以從這些條款中獲得一些幫助。


在本文中,我們將會(huì)看一看這些未可知的益處。這是由于它的未可知,我們無法為其進(jìn)行完全的分類。不過,我們?nèi)匀煌ㄟ^研究為了一個(gè)C程序的運(yùn)行所需要做的事來做到這些。我們假設(shè)讀者對(duì)C語言至少有個(gè)粗淺的了解。


第一部分研究了當(dāng)程序被劃分為記號(hào)時(shí)會(huì)發(fā)生的問題。第二部分繼續(xù)研究了當(dāng)程序的記號(hào)被編譯器組合為聲明、表達(dá)式和語句時(shí)會(huì)出現(xiàn)的問題。第三部分研究了由多個(gè)部分組成、分別編譯并綁定到一起的C程序。第四部分處理了概念上的誤解:當(dāng)一個(gè)程序具體執(zhí)行時(shí)會(huì)發(fā)生的事情。第五部分研究了我們的程序和它們所使用的常用庫之間的關(guān)系。在第六部分中,我們注意到了我們所寫的程序也不并不是我們所運(yùn)行的程序;預(yù)處理器將首先運(yùn)行。最后,第七部分討論了可移植性問題:一個(gè)能在一個(gè)實(shí)現(xiàn)中運(yùn)行的程序無法在另一個(gè)實(shí)現(xiàn)中運(yùn)行的原因。


1 詞法缺陷

編譯器的第一個(gè)部分常被稱為詞法分析器(lexical analyzer)。詞法分析器檢查組成程序的字符序列,并將它們劃分為記號(hào)(token)一個(gè)記號(hào)是一個(gè)有一個(gè)或多個(gè)字符的序列,它在語言被編譯時(shí)具有一個(gè)(相關(guān)地)統(tǒng)一的意義。在C中, 例如,記號(hào)->的意義和組成它的每個(gè)獨(dú)立的字符具有明顯的區(qū)別,而且其意義獨(dú)立于->出現(xiàn)的上下文環(huán)境。


另外一個(gè)例子,考慮下面的語句:


if(x > big) big = x;


該語句中的每一個(gè)分離的字符都被劃分為一個(gè)記號(hào),除了關(guān)鍵字if和標(biāo)識(shí)符big的兩個(gè)實(shí)例。


事實(shí)上,C程序被兩次劃分為記號(hào)。首先是預(yù)處理器讀取程序。它必須對(duì)程序進(jìn)行記號(hào)劃分以發(fā)現(xiàn)標(biāo)識(shí)宏的標(biāo)識(shí)符。它必須通過對(duì)每個(gè)宏進(jìn)行求值來替換宏調(diào)用。最后,經(jīng)過宏替換的程序又被匯集成字符流送給編譯器。編譯器再第二次將這個(gè)流劃分為記號(hào)。


在這一節(jié)中,我們將探索對(duì)記號(hào)的意義的普遍的誤解以及記號(hào)和組成它們的字符之間的關(guān)系。稍后我們將談到預(yù)處理器。


1.1 = 不是 ==

從Algol派生出來的語言,如Pascal和Ada,用:=表示賦值而用=表示比較。而C語言則是用=表示賦值而用==表示比較。這是因?yàn)橘x值的頻率要高于比較,因此為其分配更短的符號(hào)。


此外,C還將賦值視為一個(gè)運(yùn)算符,因此可以很容易地寫出多重賦值(如a = b = c),并且可以將賦值嵌入到一個(gè)大的表達(dá)式中。


這種便捷導(dǎo)致了一個(gè)潛在的問題:可能將需要比較的地方寫成賦值。因此,下面的語句好像看起來是要檢查x是否等于y:


if(x = y)
foo();


而實(shí)際上是將x設(shè)置為y的值并檢查結(jié)果是否非零。在考慮下面的一個(gè)希望跳過空格、制表符和換行符的循環(huán):


while(c == ' ' || c = '\t' || c == '\n')
c = getc(f);


在與'\t'進(jìn)行比較的地方程序員錯(cuò)誤地使用=代替了==。這個(gè)“比較”實(shí)際上是將'\t'賦給c,然后判斷c的(新的)值是否為零。因?yàn)?\t'不為零,這個(gè)“比較”將一直為真,因此這個(gè)循環(huán)會(huì)吃盡整個(gè)文件。這之后會(huì)發(fā)生什么取決于特定的實(shí)現(xiàn)是否允許一個(gè)程序讀取超過文件尾部的部分。如果允許,這個(gè)循環(huán)會(huì)一直運(yùn)行。


一些C編譯器會(huì)對(duì)形如e1 = e2的條件給出一個(gè)警告以提醒用戶。當(dāng)你趨勢(shì)需要先對(duì)一個(gè)變量進(jìn)行賦值之后再檢查變量是否非零時(shí),為了在這種編譯器中避免警告信息,應(yīng)考慮顯式給出比較符。換句話說,將:


if(x = y)
foo();


改寫為:


if((x = y) != 0)
foo();


這樣可以清晰地表示你的意圖。


1.2 & 和 | 不是 && 和 ||

容易將==錯(cuò)寫為=是因?yàn)楹芏嗥渌Z言使用=表示比較運(yùn)算。 其他容易寫錯(cuò)的運(yùn)算符還有&和&&,或|和||,這主要是因?yàn)镃語言中的&和|運(yùn)算符于其他語言中具有類似功能的運(yùn)算符大為不同。我們將在第4節(jié)中貼近地觀察這些運(yùn)算符。


1.3 多字符記號(hào)

一些C記號(hào),如/、*和=只有一個(gè)字符。而其他一些C記號(hào),如/*和==,以及標(biāo)識(shí)符,具有多個(gè)字符。當(dāng)C編譯器遇到緊連在一起的/和*時(shí),它必須能夠決定是將這兩個(gè)字符識(shí)別為兩個(gè)分離的記號(hào)還是一個(gè)單獨(dú)的記號(hào)。C語言參考手冊(cè)說明了如何決定:“如果輸入流到一個(gè)給定的字符串為止已經(jīng)被識(shí)別為記號(hào),則應(yīng)該包含下一個(gè)字符以組成能夠構(gòu)成記號(hào)的最長(zhǎng)的字符串”。因此,如果/是一個(gè)記號(hào)的第一個(gè)字符,并且/后面緊隨了一個(gè)*,則這兩個(gè)字符構(gòu)成了注釋的開始,不管其他上下文環(huán)境。


下面的語句看起來像是將y的值設(shè)置為x的值除以p所指向的值:


y = x/*p /* p 指向除數(shù) */;


實(shí)際上,/*開始了一個(gè)注釋,因此編譯器簡(jiǎn)單地吞噬程序文本,直到*/的出現(xiàn)。換句話說,這條語句僅僅把y的值設(shè)置為x的值,而根本沒有看到p。將這條語句重寫為:


y = x / *p /* p 指向除數(shù) */;


或者干脆是


y = x / (*p) /* p指向除數(shù) */;


它就可以做注釋所暗示的除法了。


這種模棱兩可的寫法在其他環(huán)境中就會(huì)引起麻煩。例如,老版本的C使用=+表示現(xiàn)在版本中的+=。這樣的編譯器會(huì)將


a=-1;


視為


a =- 1;



a = a - 1;


這會(huì)讓打算寫


a = -1;


的程序員感到吃驚。


另一方面,這種老版本的C編譯器會(huì)將


a=/*b;


斷句為


a =/ *b;


盡管/*看起來像一個(gè)注釋。


1.4 例外

組合賦值運(yùn)算符如+=實(shí)際上是兩個(gè)記號(hào)。因此,


a + /* strange */ = 1



a += 1


是一個(gè)意思。看起來像一個(gè)單獨(dú)的記號(hào)而實(shí)際上是多個(gè)記號(hào)的只有這一個(gè)特例。特別地,


p - > a


是不合法的。它和


p -> a


不是同義詞。


另一方面,有些老式編譯器還是將=+視為一個(gè)單獨(dú)的記號(hào)并且和+=是同義詞。


1.5 字符串和字符

單引號(hào)和雙引號(hào)在C中的意義完全不同,在一些混亂的上下文中它們會(huì)導(dǎo)致奇怪的結(jié)果而不是錯(cuò)誤消息。


包圍在單引號(hào)中的一個(gè)字符只是書寫整數(shù)的另一種方法。這個(gè)整數(shù)是給定的字符在實(shí)現(xiàn)的對(duì)照序列中的一個(gè)對(duì)應(yīng)的值。因此,在一個(gè)ASCII實(shí)現(xiàn)中,'a'和0141或97表示完全相同的東西。而一個(gè)包圍在雙引號(hào)中的字符串,只是書寫一個(gè)有雙引號(hào)之間的字符和一個(gè)附加的二進(jìn)制值為零的字符所初始化的一個(gè)無名數(shù)組的指針的一種簡(jiǎn)短方法。


線面的兩個(gè)程序片斷是等價(jià)的:


printf("Hello world\n");


char hello[] = {
'H', 'e', 'l', 'l', 'o', ' ',
'w', 'o', 'r', 'l', 'd', '\n', 0
};
printf(hello);


使用一個(gè)指針來代替一個(gè)整數(shù)通常會(huì)得到一個(gè)警告消息(反之亦然),使用雙引號(hào)來代替單引號(hào)也會(huì)得到一個(gè)警告消息(反之亦然)。但對(duì)于不檢查參數(shù)類型的編譯器卻除外。因此,用


printf('\n');


來代替


printf("\n");


通常會(huì)在運(yùn)行時(shí)得到奇怪的結(jié)果。


由于一個(gè)整數(shù)通常足夠大,以至于能夠放下多個(gè)字符,一些C編譯器允許在一個(gè)字符常量中存放多個(gè)字符。這意味著用'yes'代替"yes"將不會(huì)被發(fā)現(xiàn)。后者意味著“分別包含y、e、s和一個(gè)空字符的四個(gè)連續(xù)存貯器區(qū)域中的第一個(gè)的地址”,而前者意味著“在一些實(shí)現(xiàn)定義的樣式中表示由字符y、e、s聯(lián)合構(gòu)成的一個(gè)整數(shù)”。這兩者之間的任何一致性都純屬巧合

]]>
C++ 語言基礎(chǔ)(2)http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2429&Page=1wangxinxin2010-12-10 14:39:53C++數(shù)據(jù)類型 新術(shù)語 C++數(shù)據(jù)類型定義編譯器在內(nèi)存中存放信息的方式。在有些編程語言中,可以向變量賦予任何數(shù)值類型。例如,下面是BASIC代碼的例子:x = 1;x = 1000;x = 3.14;x = 457000;在BASIC中,翻譯器能考慮根據(jù)數(shù)字長(zhǎng)度和類型分配空間。而在C++,則必須先聲明變量類型再使用變量:int x1 = 1;int x = 1000;float y = 3.14;long z = 457000;這樣,編譯器就可以進(jìn)行類型檢查,確保程序運(yùn)行時(shí)一切順利。數(shù)據(jù)類型使用不當(dāng)會(huì)導(dǎo)致編譯錯(cuò)誤或警告,以便分析和糾正之后再運(yùn)行。有些數(shù)據(jù)類型有帶符號(hào)和無符號(hào)兩種。帶符號(hào)(signed)數(shù)據(jù)類型可以包含正數(shù)和負(fù)數(shù),而無符號(hào)(unsigned)數(shù)據(jù)類型只能包含正數(shù)。表1.1列出了C++中的數(shù)據(jù)類型、所要內(nèi)存量和可能的取值范圍。 表1.1C++數(shù)據(jù)類型(32位程序) 數(shù)據(jù)類型 字節(jié) 數(shù)取值范圍 char 1 -128到126 unsigned char 1 0到255 short 2 -32,768到32,767 unsigned short 2 0到65,535 long 4 -2,147,483,648到2,147,483,648 unsigned long 4 0到4,294,967,295 int 4 同long unsigned int 4 同unsigned long float 4 1.2E-38到3.4E381 double 8 2.2E-308到1.8E3082 bool 1 true或false 從上表可以看出,int與long相同。那么,為什么C++還要區(qū)分這兩種數(shù)據(jù)類型呢?實(shí)際上這是個(gè)遺留問題。在16位編程環(huán)境中,int要求2個(gè)字節(jié)而long要求4個(gè)字節(jié)。而在32位編程環(huán)境中,這兩種數(shù)據(jù)都用4個(gè)字節(jié)存放。C++Builder只生成32位程序,所以int與long相同。說明 在C++ Builder和BorLand C++ 5.0中,Bool是個(gè)真正的數(shù)據(jù)類型。有些C++編譯器有Bool關(guān)鍵字,則Bool不是個(gè)真正的數(shù)據(jù)類型。有時(shí)Bool只是個(gè)typedef,使Bool等價(jià)于int。typedef實(shí)際上建立別名,使編譯器在一個(gè)符號(hào)與另一符號(hào)間劃上等號(hào)。typedef的語法如下:typedef int Bool;這就告訴編譯器:Bool是int的別名。說明 只有double和float數(shù)據(jù)類型使用浮點(diǎn)數(shù)(帶小數(shù)點(diǎn)的數(shù))。其它數(shù)據(jù)類型只涉及整數(shù)值。盡管integer數(shù)據(jù)類型也可以指定帶小數(shù)點(diǎn)的數(shù)值,但小數(shù)部分會(huì)舍棄,只將整數(shù)部分賦予整型變量,例如:int x=3.75;得到的x取值為3。注意,這個(gè)整數(shù)值并不是四舍五入,而是放棄小數(shù)部分。順便說一句,大多數(shù)Windows程序很少用到浮點(diǎn)數(shù)。C++可以在必要時(shí)進(jìn)行不同數(shù)據(jù)類型間的換算。例如:short result;long num1 = 200;long num2 = 200;result = num1 * num2;這里我想將兩個(gè)長(zhǎng)整型的積賦予一個(gè)短整型。盡管這個(gè)公式混用了兩種數(shù)據(jù)類型,但C++能夠進(jìn)行換算。計(jì)算結(jié)果會(huì)怎樣呢?結(jié)果會(huì)讓你大吃一驚,是25536,這是繞接(wrop)的結(jié)果。從表1.1可以看出,短整型的最大取值為32767,在最大值之上加1會(huì)怎么樣呢?得到的是32768。這實(shí)際上與汽車?yán)锍逃?jì)從99999回到00000的道理一樣。為了說明這點(diǎn),請(qǐng)輸入并運(yùn)行下列清單1.3中包含的程序。 清單1.3Wrapme.cpp 1: #include <iostream.h> 2: #include <conio.h> 3: #pragma hdrstop 4: 5: int main(int argc,char **argv) 6: { 7:short x = 32767; 8:cout << " x = " << x << endl; 9:x++; 10: cout << " x = " << x << endl; 11: getch(); 12: return 0; 13: } 說明后面幾節(jié)要介紹的有些清單沒有下列語句: #include<condefs.h> C++ Builder生成新的控制臺(tái)應(yīng)用程序時(shí)會(huì)自動(dòng)加上這條語句。這在你所用的程序中不是必須的,所以代碼清單中將其省略。無論有無這條語句,程序運(yùn)行結(jié)果是一致的。分析輸出結(jié)果為:x=32767 x=32768如果用int數(shù)據(jù)類型,則不會(huì)有這個(gè)問題,因?yàn)閕nt數(shù)據(jù)類型的取值范圍在正向20億之間,一般不會(huì)有繞回的問題。但這時(shí)程序可能會(huì)稍大一些,因?yàn)閕nt需要4字節(jié)存儲(chǔ),而short只需要2字節(jié)存儲(chǔ)。對(duì)于大多數(shù)應(yīng)用程序,這個(gè)差別是不顯著的。前面介紹了自動(dòng)類型換算。有時(shí)C++無法進(jìn)行換算,這時(shí)可能在編譯器中產(chǎn)生編譯錯(cuò)誤,說Cannot convert from x to y(無法從x換算到Y(jié))。編譯器也可能警告說Conversion might lose significant digits(換算可能丟失顯著位)。提示 編譯器警告應(yīng)當(dāng)作編譯器錯(cuò)誤,因?yàn)樗砻鞒隽隋e(cuò)誤。我們應(yīng)努力生成無警告的編譯。有時(shí)警告無法避免,但一定要認(rèn)真檢查所有警告。應(yīng)充分了解警告的原因并盡量予以糾正。]]>在Java與C程序間進(jìn)行socket通信的討論http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2428&Page=1wangxinxin2010-12-10 14:34:59
  使用socket在Java程序與C程序間進(jìn)行進(jìn)程間通信。本文主要描述了在同C程序進(jìn)行通信的Client端的Java實(shí)現(xiàn)功能。

  1.1. 使用的語言

  Client端:Java,JVM(JDK1.3)

  Server端:C,UNIX(Sun Solaris)

  1.2. 討論范圍

  數(shù)據(jù)發(fā)送:只涉及到Java中int整型系列的討論,包括byte,short,int。

  數(shù)據(jù)接受:涉及到byte,short,int,long,float,double,char。

  1.3.Java與C的數(shù)據(jù)類型的比較

  Type Java C

  short 2-Byte 2-Byte

  int 4-Byte 4-Byte

  long 8-Byte 4-Byte

  float 4-Byte 4-Byte

  double 8-Byte 8-Byte

  boolean 1-bit N/A

  byte 1-Byte N/A

  char 2-Byte 1-Byte

  2. 實(shí)現(xiàn)

  輸出流:使用OutputStream流發(fā)送數(shù)據(jù)到C程序端。

  輸入流:使用DataInputStream流從C程序端接受數(shù)據(jù)

  2.1. 數(shù)據(jù)發(fā)送

  由于DataOutputStream流對(duì)于Java各個(gè)基本數(shù)據(jù)類型都相應(yīng)地提供了“寫”方法,如wrightShort和wrightInt等,因此當(dāng)進(jìn)行進(jìn)程間通信(sockect通信)時(shí),我們總是優(yōu)先考慮使用DataOutputStream流。

  下面我們對(duì)DataOutputStream流及其成員方法進(jìn)行分析:

  2.1.1. DataOutputStream流

  DataOutputStream流實(shí)現(xiàn)了接口DataOutput。

  本文只討論writeByte(int v)、writeShort(int v)和writeInt(int v)部分(這是因?yàn)槲覀冃枰l(fā)送的數(shù)據(jù)只涉及到int,short和byte,其它的long,double等則不在這里介紹),而且它們都有一個(gè)共同的特征,即唯一的int類型的輸入?yún)?shù)。

  這些成員方法的功能描述也為我們以后手動(dòng)進(jìn)行字節(jié)順序轉(zhuǎn)換,提供了理論依據(jù)。

  2.1.2.

  網(wǎng)絡(luò)字節(jié)順序

  規(guī)定:網(wǎng)絡(luò)上傳輸?shù)臄?shù)據(jù)統(tǒng)一采用Big Endian格式(即“高字節(jié)在前”),我們稱之為“網(wǎng)絡(luò)字節(jié)順序”(network byte order)。

  Big Endian格式:

  高字節(jié) 低字節(jié)

  1 2 3 4

  Byte[0] byte[1] byte[2] byte[3]輸出緩沖區(qū)

  因此,無論本機(jī)字節(jié)順序采用的那種順序,在發(fā)送到網(wǎng)絡(luò)之前都要轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)順序,才能進(jìn)行傳輸。特別是在Java與C兩種不同語言的應(yīng)用程序間進(jìn)行通信時(shí),這一點(diǎn)優(yōu)為重要。(若是兩個(gè)Java程序間通信時(shí)可能只要保證接受與發(fā)送采用相同的字節(jié)順序,則可以不進(jìn)行轉(zhuǎn)換格式,但這種做法并不好,不具有良好的移植性)

  2.1.3. 數(shù)據(jù)發(fā)送:手動(dòng)字節(jié)轉(zhuǎn)換 / writeInt方法

  以writeInt(int v)為例進(jìn)行描述:

  閱讀DataOutput的writeInt(int v)方法的文檔可知:

  使用writeInt方法可以寫一個(gè)4-byte的int值v到輸出流,其字節(jié)順序?yàn)?

  (byte)(0xff & (v >> 24)) byte[0] 高字節(jié)

  (byte)(0xff & (v >> 16)) byte[1]

  (byte)(0xff & (v >> 8)) byte[2]

  (byte)(0xff & v) byte[3] 低字節(jié)

  這樣的字節(jié)順序?yàn)锽ig Endian格式,標(biāo)準(zhǔn)的“網(wǎng)絡(luò)字節(jié)順序”。

  但是在實(shí)際工作中輸出流采用DataOutputStream.readInt(int)方法時(shí)寫數(shù)據(jù)出錯(cuò),需要自己手動(dòng)按照以上所說的對(duì)需要寫的v值進(jìn)行轉(zhuǎn)換(通過移位完成),轉(zhuǎn)換的代碼如下所示,可參見程序SocketClient.java中的ByteConverter.intToByte()方法。

  static public final byte[] intToByte(

  int value, int offset, int length, byte[] buffer)

  { // High byte first on network

  for (int i=0,j=length-1; i<length; i++,j--) {

  if ( j+offset >= 0 && j+offset < 1024 ) {

  buffer[j+offset] = (byte)( (value >> i*8) & 0xFF );

  } else {

  System.out.println (

  "Array index out of the bounds:Index=" + (j+offset) );

  }

  }

  return buffer;

  }

  2.2. 數(shù)據(jù)接收

  同數(shù)據(jù)發(fā)送相同,由于DataInputStream流對(duì)于Java各個(gè)基本數(shù)據(jù)類型都相應(yīng)地提供了“讀”方法,如readShort和readInt等,因此當(dāng)進(jìn)行進(jìn)程間通信(sockect通信)時(shí),我們總是優(yōu)先考慮使用DataInputStream流。

  而與數(shù)據(jù)發(fā)送不同的是,DataInputStream下的成員方法經(jīng)實(shí)際測(cè)試,“基本上可以”根據(jù)數(shù)據(jù)類型正確讀出相應(yīng)的數(shù)值。

  但并非完美,特別是與不同語言的應(yīng)用程序進(jìn)行通信時(shí)(如C)。

  根據(jù)表1(Java與C的數(shù)據(jù)類型的比較)可知:

  (1)long型的字節(jié)數(shù)在Java和C中相差4個(gè)字節(jié):

  因此由readLong方法讀來的數(shù)值應(yīng)進(jìn)行帶符號(hào)的右移32(4-byte)位才能得到在C程序中相應(yīng)的long型數(shù)值。

  Type Java C

  long 8-Byte 4-Byte

  (2)由于Java中的char型為2個(gè)字節(jié),C中的char型為1個(gè)字節(jié),因此不能使用readChar方法來讀取C程序中的char數(shù)值。

  然而在Java中byte型為1個(gè)字節(jié)長(zhǎng),因此可以使用readByte方法得到C程序中的char型數(shù)值。

  Type Java C

  byte 1-Byte N/A

  char 2-Byte 1-Byte

  最近一個(gè)項(xiàng)目中c/c++代碼和java代碼通信,c那邊用的是UINT類型,穿過來時(shí)4個(gè)字節(jié),在這邊java要把這4個(gè)字節(jié)轉(zhuǎn)換成數(shù)值。這里就出現(xiàn)了一個(gè)java和c數(shù)值類型存儲(chǔ)順序不同的問題了。

  從微觀上來看,也就是從單個(gè)byte來看,在c中和在java中存放的順序是一樣的,例如31在c中表示為0x1F(從左往右輸出表示),在java中也是如此。但是如果從宏觀,也就是每個(gè)byte之間的順序,java和c就大不一樣了。從宏觀來說java也是高高低低,高位放左邊低位放右邊,但是c中剛好相反。

  如果在c中,31L的16進(jìn)制從左往右輸出結(jié)果是1F00000000000000,java中是000000000000001F。]]>
到底C#是編譯語言還是解釋語言http://m.scb-ycwb.com/bbs/dispbbs.asp?BoardID=63&ID=2427&Page=1wangxinxin2010-12-10 14:33:43我們這里須要討論的是C#是編譯語言還是解釋語言?將從解釋來執(zhí)行 討論,并結(jié)合流程圖來說明。希望最后的結(jié)論,能對(duì)大家有所幫助。

“C# Java是解釋型語言?Oh my god”

“引用vls:C# Java是解釋型語言?Oh my god

呵呵 我也很詫異“

“引用DiggingDeeply:@vlsC#不是解釋行語言,那JIT是干啥用的?

無知并不可憐,無知還不知道自己無知才叫可憐”

“。。。但如果因?yàn)樗?一邊變換一邊執(zhí)行", 就將其當(dāng)作解釋語言……只能說你看到表象卻沒抓住本質(zhì)。”

很是無語,既然您認(rèn)為別人無知那您的有知拿出來給無知的人看看,行不?

拋開這些不談,誰能給編譯型和解釋型給下個(gè)解釋。無一例外,要么就是某人的博客,要么就是搜索來的網(wǎng)頁,再要么就是放個(gè)闕詞就消散,這些作為論據(jù)充分不?

昨天翻了翻龍書,也沒有給這兩個(gè)概念下細(xì)致的解釋,可見兩個(gè)概念是很難下個(gè)精確的解釋的。

在<<programming language="" Pragmatics>>(by Michaei L. Scott)這本書里面,我找到了有關(guān)的解釋和說明,特摘錄如下

Compilation and Interpretation

高級(jí)語言里一個(gè)程序的編譯和執(zhí)行大概是 下面的情況:

討論:到底C#是編譯語言還是解釋語言圖片1

點(diǎn)擊查看大圖

編譯器將高級(jí)語言從源代碼翻譯成與之等價(jià)的目標(biāo)程序(就相當(dāng)于從中文翻譯成中文),而后就隱退了。在隨后的某個(gè)時(shí)刻,用戶啟動(dòng)目標(biāo)程序由操作系統(tǒng)執(zhí)行。實(shí)現(xiàn)高級(jí)語言的另外一種形式為解釋:

討論:到底C#是編譯語言還是解釋語言圖片2

 

與編譯不同的是,解釋器在目標(biāo)程序(其實(shí)根本就沒有目標(biāo)程序,只是與編譯來比較)執(zhí)行期間,解釋器一直隨之運(yùn)行。這種執(zhí)行流程完全由解釋器控制的。從效果上看,解釋器實(shí)現(xiàn)了一臺(tái)“虛擬計(jì)算機(jī)”,其“機(jī)器語言”就是高級(jí)語言,解釋器一次讀入一條或多條語句,按照其自身規(guī)定的形式去執(zhí)行相應(yīng)的操作。一般說來,解釋比編譯有著很好的靈活性;編譯一般有著較好的性能。但是有些語言確是采用了兩者的混合形式:

討論:到底C#是編譯語言還是解釋語言圖片3

點(diǎn)擊查看大圖

書中的原文:”如果原始階段的翻譯器比較基本,我們就說這個(gè)語言是“解釋的”。如果翻譯器很復(fù)雜,我們就說這一語言是“編譯的”。現(xiàn)在兩者的區(qū)分變得有些模糊了,因?yàn)椤盎?”和“復(fù)雜”都是修飾性術(shù)語,也因?yàn)橥耆赡艹霈F(xiàn)用一個(gè)編譯器(復(fù)雜的翻譯流程)生成代碼,而后又由一個(gè)復(fù)雜的虛擬機(jī)(解釋器)執(zhí)行。對(duì)于最后這種情況,如果翻譯器對(duì)程序做了徹底的分析(而不是做某種“機(jī)械的”變換),而且有關(guān)的中間語言程序與源程序并沒有很強(qiáng)的相似性,我們還是說這個(gè)語言是編譯的。這兩種特征 ----徹底的分析和非平凡的變換-----是刻畫編譯形式的標(biāo)志性特征。“

根據(jù)以上標(biāo)準(zhǔn),首先CSC只是對(duì)C#到IL做”機(jī)械“的翻譯,而且C#和IL之間有很強(qiáng)的相似性,因?yàn)閮烧叩某绦虼a幾乎可以100%相互轉(zhuǎn)換(比如reflector可以將C#反編成IL,也可以將IL反編為C#)。您認(rèn)為呢?

PS:再者某些人認(rèn)為的ngen和cache程序集其實(shí)也是支持C#是解釋語言的結(jié)論,因?yàn)榫幾g型語言因?yàn)樾阅艿奶烊灰蛩厥遣豁氁@些手段的。也許我是錯(cuò)的,請(qǐng)您不吝賜教,感激涕零.本人禁止了不負(fù)責(zé)任的匿名評(píng)論,請(qǐng)大家海涵。

]]>
主站蜘蛛池模板: 天天做天天爱天天干| 国产99视频免费精品是看6| 欧美日韩免费看| 啦啦啦www免费视频| 日韩免费视频一区| 国产精品亚洲综合五月天| 亚洲熟妇丰满多毛XXXX| 天天综合网网欲色| 男人的好电影在线观看| ww4545四虎永久免费地址| 夜夜精品视频一区二区| 黄在线观看www免费看| 亚洲欧美激情精品一区二区| 国产高清自拍视频| 欧美巨大黑人精品videos人妖| 中文字幕在线永久在线视频2020 | 中文字幕高清在线观看| 国产精品第1页| 樱桃视频影院在线播放| 黄色大片在线观看| 中文字幕影片免费在线观看| 又色又爽又黄的视频女女高清| 欧美午夜伦y4480私人影院| 免费视频www| 久久久久久久99精品免费 | 免费看特黄特黄欧美大片| 日韩在线永久免费播放| 老师你的兔子好软水好多作文高清| 久久久99精品成人片中文字幕| 午夜影皖普通区| 欧洲多毛裸体XXXXX| 色狠狠色狠狠综合天天| 亚洲校园春色另类激情| 天堂网www中文在线| 最近中文字幕高清字幕在线视频| 色噜噜成人综合网站| a在线视频免费观看| 亚洲高清毛片一区二区| 国产在播放一区| 日本成人在线免费| 浪潮AV色综合久久天堂|