亚洲一一在线,亚洲午夜精品,中文字幕欧美日韩一区二区三区http://www.bjzhda.cnzh-cn曙海教育集團論壇http://www.bjzhda.cnRss Generator By Dvbbs.Netofficeoffice@126.comimages/logo.gif曙海教育集團論壇Visual C++ 1.0:C++編譯器的終結(jié)者http://www.martymets.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))。由于匯編語言依賴于計算機硬件,因此程序的可移植性和可讀性就比較差。為了提高程序的可讀性和可移植性,并能實現(xiàn)匯編語言的某些功能(如匯編語言可以直接對硬件進行操作、對內(nèi)存地址進行操作和位操作等)。于是,C語言便應運而生了。

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

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

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

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

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

  編輯器之爭

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

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

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

  自Borland C/C++ 4.0一役大敗之后,Visual C/C++雖取得了勝利,但此時在C/C++市場上也加入了另外兩個堅強的對手,那就是Symantec C/C++和Watcom C/C++。

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

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

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

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

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

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

  隨后,Windows 3.0出現(xiàn)了。Windows 3.0尤其是3.1,為個人計算機引進了真正的IDE時代。但是,Microsoft卻把精力更多地集中在C編譯器的內(nèi)部支持上,而不是把它的界面升級到一個新的時代。盡管如此,Microsoft C/C++ 7.0卻引入了對C++的支持,并引進了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仍提供對16位的支持,但它僅用來創(chuàng)建32位程序。

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

  Visual C++ 4.0引入了Internet的支持,并為Internet編程而設計的新類庫。

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

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

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

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

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

  MFC和Visual C++

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

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

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

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

  最后一個16位的Visual C++編譯器是1993年12月推出的Visual C++ 1.5,直到今天,一些為Windows 3.1編寫16位應用程序的程序員還在使用這個版本。1994年9月,32位的MFC 3.0伴隨著Visual C++ 2.0的一道面市,在今天的計算機圖書市場上,還有著大量的關于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ā)展成一個穩(wěn)定和涵蓋極廣的C++類庫,為成千上萬的Win32程序員所使用。MFC庫是可擴展的,它和Windows技術的最新發(fā)展到目前為止始終是同步的。并且,MFC類庫使用了標準的Windows命名約定和編碼格式,所以有經(jīng)驗的Windows SDK程序員很容易過渡到MFC。MFC結(jié)合了Windows SDK編程概念和面向?qū)ο蟮某绦蛟O計技術,從而具有極大靈活性和易用性。
]]>
編程語言之兵器譜(六)http://www.martymets.com/bbs/dispbbs.asp?BoardID=63&ID=2445&Page=1wangxinxin2010-12-10 15:29:28微機史上最強的編程語言是C/C++。C最大的特色就是指針,指哪兒打哪兒,如果把指針做到應用自如,那就是無往而不勝了, C/C++對應兵器譜上第3位小李飛刀,刀無虛發(fā),畢竟現(xiàn)在的Web時代,后來居上的JAVA和.Net成為主流的開發(fā)語言,所以只能把它屈居第三位了。

 

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

 

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

 

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

 

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

 

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

 

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

 

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

 

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

 

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

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

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

圖片點擊可在新窗口打開查看

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

]]>
從VC++6.0不足看Visual C++2010新特性http://www.martymets.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++是構建Windows平臺下應用程序功能最強大而又最復雜的工具,是目前世界上使用最多的開發(fā)工具之一,應用極度廣泛,從桌面應用程序到服務器程序,從系統(tǒng)軟件到應用軟件,圖形圖像,語音技術,設備驅(qū)動,網(wǎng)絡安全,加密解密等等幾乎無處不在。主流的3 種操作系統(tǒng)Windows,Linux,Unix內(nèi)核都是用C語言和匯編語言寫的,而上層的高級特性都是用C++編寫。

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

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

  Visual C++2010 新特性

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

  (1)Ribbion界面設計可視化

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

  1. 打開Microsoft Visual Studio 2010,點擊“文件->新建->項目”,打開“新建項目”窗體

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

圖片點擊可在新窗口打開查看
 

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

圖片點擊可在新窗口打開查看
 

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

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

圖片點擊可在新窗口打開查看

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

 對話框

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

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

  2. 在 Tools 彈出菜單中添加一個菜單項,命名為 Run WCE First Dialog;

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

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

  4. 插入一個新的對話框資源,并設置其標題為 WCE First Dialog,資源標號為 IDD_FIRST_DLG;

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

  6. 將 Cancel 按鈕的標題改為 Start,并將其資源標號改為 IDB_START_BTN;

  7. 從控件面板上拉下一個進度控件并放置到對話框中。不要修改該進度控件的風格(styles)、標題(caption)和資源標號(resource ids);

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

  9. 使用 ClassWizard 綁定該對話框資源到一個新的類:CWCEFirstDialog;

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

  11. 為 Start 按鈕添加一個命令按鈕句柄;

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

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

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
}


  下一步,當用戶點擊 Start 按鈕時,進度控件的值要開始增長。在增長結(jié)束時,還要顯示一個消息框。下列代碼完成上述任務:

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

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


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

]]>
C和C++語言學習總結(jié)http://www.martymets.com/bbs/dispbbs.asp?BoardID=63&ID=2441&Page=1wangxinxin2010-12-10 15:15:351、if,for,switch,goto
2、#define,const
3、文件拷貝的代碼,動態(tài)生成內(nèi)存,復合表達式,strcpy,memcpy,sizeof
4、函數(shù)參數(shù)傳遞,內(nèi)存分配方式,內(nèi)存錯誤表現(xiàn),malloc與new區(qū)別
5、類重載、隱藏與覆蓋區(qū)別,extern問題,函數(shù)參數(shù)的缺省值問題,宏代碼與內(nèi)聯(lián)函數(shù)區(qū)別
6、構造和析構的次序,String函數(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)    可以等價為  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ù)或者強制為整數(shù),由于char實際上是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ù)類型,編譯器會進行類型安全檢查,而#define沒有數(shù)據(jù)類型,
  const的常量可以進行調(diào)試,但宏常量不能進行調(diào)試.
2、const的使用方法
在全局定義 const float PI=3.1415926
在類中定義
class A
{...
    A(int size);
    const int SIZE;
};
A::A(int size):SIZE(size)
{
  ...
}
對參數(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代表的地址是不能改變的;

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

當是輸入?yún)?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ù)的效率比較低,因為函數(shù)體內(nèi)將產(chǎn)生A類型的臨時對象用于復制參數(shù)a,而臨時對象的構造、復制和析構過程都需要消耗時間
最好用const A&a的原因是A&a中的a可以被改變,A&a和const A&a的好處在于都不會產(chǎn)生臨時對象,效率高;

const A Func(const A&a )const的好處
第一個const表示返回的是個內(nèi)部產(chǎn)生的對象,它不能被修改
const A Func(...)
{...}
const A a=Func(...);//不能是A a=Func(...);
第二個const表示輸入的參數(shù)是引用傳遞,函數(shù)內(nèi)部不會產(chǎn)生臨時對象,而且這個對象不能被內(nèi)部修改
第三個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++;//編譯錯誤,企圖修改數(shù)據(jù)成員m_num;
  Pop();//編譯錯誤,企圖調(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;
}

動態(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;
}
------------------------------------------
錯誤的代碼:
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"); // 運行錯誤
  cout < < str < < endl;//運行錯誤
  free(str);//運行錯誤
}

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; 
}

復合表達式
d = (a = b + c) + r ;
該表達式既求a 值又求d 值.應該拆分為兩個獨立的語句:
a = b + c;
d = a + r;

if (a < b < c) // a < b < c 是數(shù)學表達式而不是程序表達式
并不表示
if ((a <b) && (b <c))
而是成了令人費解的
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é)長度
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 (所有指針類型長度都一樣)(char*,int*,float*,double*)
enum                    4

ii.在32位操作系統(tǒng)中,定義或函數(shù)中的大小
char a[]="hello";
char b[100];
char *p=a;
類型                  字節(jié)長度
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://www.martymets.com/bbs/dispbbs.asp?BoardID=63&ID=2440&Page=1wangxinxin2010-12-10 15:13:24在Java中,對變量和方法的訪問控制是通過訪問修飾符來實現(xiàn)的。Java定義了4種
訪問級別:公共(public)、受保護(protected)、私有(private)和友好(friendly)。
公共類型的方法及變量可從任意類進行訪問;受保護類型的方法及變量只能從當前
類及其子類訪問;私有類型的方法及變量則只能從當前類訪問。如果未給出這三種
類型中任意一種的顯式說明 ,表明相應的方法或變量屬于"友好"類型,從而可由屬
于同一"包"(package)內(nèi)的所有類進行訪問。在Java內(nèi),"包"是一個單獨的編譯單
位,它是具有某種共性的類所組成的集合。通過定義包這個單位,可實現(xiàn)相關對象
之間的相互訪問,同時把這些對象與包之外的其它對象隔離。 

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

2. 與C++的差別 

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

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

·指針 ·多重繼承 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    內(nèi)存管理

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

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

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

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

    資源管理

    CLR只有在資源管理方面,才能勝過本地C++。Bjarne Stroustrup的"資源獲取即初始化"的技術觀點,基本定義了資源類型的模式,即類的構造函數(shù)獲取資源,析構函數(shù)釋放資源。這些類型是被當作堆棧上的局部對象,或復雜類型中的成員,其析構函數(shù)自動釋放先前分配的資源。一如Stroustrup所言"對垃圾回收機制來說,C++是最好的語言,主要是因為它生成很少的垃圾。"

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

    因為必須要調(diào)用一個方法來釋放資源,由此帶來的問題是,現(xiàn)在更難編寫"全無異常"的代碼了。因為異常隨時都可能發(fā)生,你不可能只是簡單地在一段代碼后,放置一個對對象的Dispose方法的調(diào)用,這樣做的話,就必須要冒資源泄漏的風險。在C#中解決這個問題的辦法是,使用try-finally塊和using語句,在面對異常時,可提供一個更可靠的辦法來調(diào)用Dispose方法。有時,構造函數(shù)也會使用這種方法,但一般的情況是,你必須要記住手工編寫它們,如果忘記了,生成的代碼可能會存在一個悄無聲息的錯誤。對缺乏真正析構函數(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));   }  } }

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

<!-- 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ā)技術的分析和總結(jié)http://www.martymets.com/bbs/dispbbs.asp?BoardID=63&ID=2437&Page=1wangxinxin2010-12-10 15:09:35
  桌面應用程序框架:MFC、VCL、QT、JavaAWTSWING、.Net

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

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

  *程序設計語言:C++Delphi(本來應該是ObjectPascal,但為了簡單,我就語言和工具混為一談吧)JavaC#(雖然他剛剛推出,但因為微軟為之傾注了大量心血,一定會成為一種重要的開發(fā)語言)

  *桌面應用程序框架:MFCVCL

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

  *COM技術:我單獨提出這項技術,是因為它無法簡單的被視為語言、桌面應用程序框架或企業(yè)應用程序框架,它與這些都有關系。

  2.1 程序設計語言

  2.1.1 C++語言的演進

  最初要從二進制代碼和匯編說起,但那太遙遠了。我們就從面向過程的語言說起吧(包括BasicCFortranPascal)。這種面向過程的高級語言終于把計算機帶入了尋常的應用領域。其中的C語言因為它的簡單和靈活造就了Unix和Windows這樣的偉大的軟件。

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

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

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

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

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

  2.1.2 Java和C#

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

  2.1.3 Delphi

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

  2.2桌面應用程序框架

  目前真正成功的桌面應用程序框架只有兩個,一個是MFC,一個是VCL,還有一些其他的,但事實上并未進入應用領域。遺憾的是我對兩個桌面應用程序框架都不精通。但這不妨礙我對他做出正確的評價。

  2.2.1MFC

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

  2.2.2VCL

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

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

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

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

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

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

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

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

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

當然,在個別情況下(對某些面向?qū)ο蟮恼Z言而言),編程人員也可以直接訪問實例變量 ,但這并不是一個值得推薦的做法,因為它違背了面向?qū)ο蟮某踔浴?nbsp;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

圖3

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

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

圖4

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

  其次,需要確定使用什么語言來開發(fā)插件,F(xiàn)在Visual C++、Visual Basic的4.0以上的版本都支持VC插件的開發(fā)。VC專門為插件開發(fā)提供了一個向?qū),可以幫你完成大部分的工作。如果使用Visual Basic的話,則需要使用一些類型庫來訪問VC集成開發(fā)環(huán)境的對象。因此,建議你使用VC來開發(fā)比較方便。

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

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

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

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

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

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

圖6

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

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

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

1.1語言特性的差異

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

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

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

十六進制表示

0x00004E20

Windows內(nèi)存表示

20 4E 00 00

Unix內(nèi)存表示

00 00 4E 20

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

?         網(wǎng)絡通信時

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

?         文件存儲和讀取時

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

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

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

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

3.  采用其他標準的編碼方式,如ASN1編碼


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

1.1.2變量的作用域差異

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

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

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

       {

              …

       }

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

       {

              …

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

II

              {

I

                     …

              }

              …

              …

       }


我們劃分出I和II兩個作用域,其中作用域II包含在作用域I當中。在Windows下,變量i的作用域是I的整個范圍,而Solaris下的i的作用域只是II的范圍。其實標準的C++語法應該是Solaris的做法,但是微軟在實現(xiàn)的時候沒有按照這個標準實現(xiàn),這就引發(fā)了我們討論的這個問題。由于這個差異,就引發(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下面確編不過去,提示第二個for循環(huán)中變量i沒有定義。相反代碼B在Solaris下可以正常編譯,而在Windows下面編不過去,提示第二個for循環(huán)中變量i重復定義。

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

C:

int i = 0;

if(cond)

{

       …

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

       {

              …

       }

       …

}

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

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

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

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

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

 

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

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

 

 

1.    基本概念

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

void __cdecl Your_Entry (void);

如果你喜歡,你可以起一個更加藝術的名字。

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

 

// VC++ Entry point

void MyEntry (void);

{

{

 

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

 

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

l         進入VC++bin目錄,缺省安裝下,它應該在如下的目錄中:

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

然后運行vcvars32.bat批處理文件,如下圖所示:

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

 

屏幕會提示順利設置了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ū)上應該有一個test0.exe文件,雙擊它發(fā)現(xiàn)什么也沒有出現(xiàn)。但是,其實它是一個不折不扣的Win32應用程序。你可以用相應工具來測試它,可以發(fā)現(xiàn)在入口點處是幾個符合C函數(shù)調(diào)用規(guī)則的幾個壓棧、數(shù)據(jù)轉(zhuǎn)移、和出棧指令。

上面用到的一些cllink程序開關選項的意義請參考MSDN

 

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

 

2.    Microsoft C/C++ Runtime Library

有了上面這些基礎,我們接著再看一看Microsoft C/C++ Runtime Library在入口點處都作了些什么。我這里給出的代碼是經(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運行時。我稍微解釋一下代碼的含義,它完成以下任務:

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

l         然后初始化進程堆棧;

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

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

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

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

具體的代碼請參見運行庫的源代碼。

 

3.    不使用運行庫編寫自己的應用邏輯

接著,我們來試試看,不使用C運行庫,并且使得我們的應用程序做些個事情。請看下面的代碼:

 

// 程序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程序的運行中界面如下:

                          。

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

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


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


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


1 詞法缺陷

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


另外一個例子,考慮下面的語句:


if(x > big) big = x;


該語句中的每一個分離的字符都被劃分為一個記號,除了關鍵字if和標識符big的兩個實例。


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


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


1.1 = 不是 ==

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


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


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


if(x = y)
foo();


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


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


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


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


if(x = y)
foo();


改寫為:


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


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


1.2 & 和 | 不是 && 和 ||

容易將==錯寫為=是因為很多其他語言使用=表示比較運算。 其他容易寫錯的運算符還有&和&&,或|和||,這主要是因為C語言中的&和|運算符于其他語言中具有類似功能的運算符大為不同。我們將在第4節(jié)中貼近地觀察這些運算符。


1.3 多字符記號

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


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


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


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


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


或者干脆是


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


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


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


a=-1;


視為


a =- 1;



a = a - 1;


這會讓打算寫


a = -1;


的程序員感到吃驚。


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


a=/*b;


斷句為


a =/ *b;


盡管/*看起來像一個注釋。


1.4 例外

組合賦值運算符如+=實際上是兩個記號。因此,


a + /* strange */ = 1



a += 1


是一個意思?雌饋硐褚粋單獨的記號而實際上是多個記號的只有這一個特例。特別地,


p - > a


是不合法的。它和


p -> a


不是同義詞。


另一方面,有些老式編譯器還是將=+視為一個單獨的記號并且和+=是同義詞。


1.5 字符串和字符

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


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


線面的兩個程序片斷是等價的:


printf("Hello world\n");


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


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


printf('\n');


來代替


printf("\n");


通常會在運行時得到奇怪的結(jié)果。


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

]]>
C++ 語言基礎(2)http://www.martymets.com/bbs/dispbbs.asp?BoardID=63&ID=2429&Page=1wangxinxin2010-12-10 14:39:53C++數(shù)據(jù)類型 新術語 C++數(shù)據(jù)類型定義編譯器在內(nèi)存中存放信息的方式。在有些編程語言中,可以向變量賦予任何數(shù)值類型。例如,下面是BASIC代碼的例子:x = 1;x = 1000;x = 3.14;x = 457000;在BASIC中,翻譯器能考慮根據(jù)數(shù)字長度和類型分配空間。而在C++,則必須先聲明變量類型再使用變量:int x1 = 1;int x = 1000;float y = 3.14;long z = 457000;這樣,編譯器就可以進行類型檢查,確保程序運行時一切順利。數(shù)據(jù)類型使用不當會導致編譯錯誤或警告,以便分析和糾正之后再運行。有些數(shù)據(jù)類型有帶符號和無符號兩種。帶符號(signed)數(shù)據(jù)類型可以包含正數(shù)和負數(shù),而無符號(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ù)類型呢?實際上這是個遺留問題。在16位編程環(huán)境中,int要求2個字節(jié)而long要求4個字節(jié)。而在32位編程環(huán)境中,這兩種數(shù)據(jù)都用4個字節(jié)存放。C++Builder只生成32位程序,所以int與long相同。說明 在C++ Builder和BorLand C++ 5.0中,Bool是個真正的數(shù)據(jù)類型。有些C++編譯器有Bool關鍵字,則Bool不是個真正的數(shù)據(jù)類型。有時Bool只是個typedef,使Bool等價于int。typedef實際上建立別名,使編譯器在一個符號與另一符號間劃上等號。typedef的語法如下:typedef int Bool;這就告訴編譯器:Bool是int的別名。說明 只有double和float數(shù)據(jù)類型使用浮點數(shù)(帶小數(shù)點的數(shù))。其它數(shù)據(jù)類型只涉及整數(shù)值。盡管integer數(shù)據(jù)類型也可以指定帶小數(shù)點的數(shù)值,但小數(shù)部分會舍棄,只將整數(shù)部分賦予整型變量,例如:int x=3.75;得到的x取值為3。注意,這個整數(shù)值并不是四舍五入,而是放棄小數(shù)部分。順便說一句,大多數(shù)Windows程序很少用到浮點數(shù)。C++可以在必要時進行不同數(shù)據(jù)類型間的換算。例如:short result;long num1 = 200;long num2 = 200;result = num1 * num2;這里我想將兩個長整型的積賦予一個短整型。盡管這個公式混用了兩種數(shù)據(jù)類型,但C++能夠進行換算。計算結(jié)果會怎樣呢?結(jié)果會讓你大吃一驚,是25536,這是繞接(wrop)的結(jié)果。從表1.1可以看出,短整型的最大取值為32767,在最大值之上加1會怎么樣呢?得到的是32768。這實際上與汽車里程計從99999回到00000的道理一樣。為了說明這點,請輸入并運行下列清單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生成新的控制臺應用程序時會自動加上這條語句。這在你所用的程序中不是必須的,所以代碼清單中將其省略。無論有無這條語句,程序運行結(jié)果是一致的。分析輸出結(jié)果為:x=32767 x=32768如果用int數(shù)據(jù)類型,則不會有這個問題,因為int數(shù)據(jù)類型的取值范圍在正向20億之間,一般不會有繞回的問題。但這時程序可能會稍大一些,因為int需要4字節(jié)存儲,而short只需要2字節(jié)存儲。對于大多數(shù)應用程序,這個差別是不顯著的。前面介紹了自動類型換算。有時C++無法進行換算,這時可能在編譯器中產(chǎn)生編譯錯誤,說Cannot convert from x to y(無法從x換算到Y(jié))。編譯器也可能警告說Conversion might lose significant digits(換算可能丟失顯著位)。提示 編譯器警告應當作編譯器錯誤,因為它表明出了錯誤。我們應努力生成無警告的編譯。有時警告無法避免,但一定要認真檢查所有警告。應充分了解警告的原因并盡量予以糾正。]]>在Java與C程序間進行socket通信的討論http://www.martymets.com/bbs/dispbbs.asp?BoardID=63&ID=2428&Page=1wangxinxin2010-12-10 14:34:59
  使用socket在Java程序與C程序間進行進程間通信。本文主要描述了在同C程序進行通信的Client端的Java實現(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. 實現(xiàn)

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

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

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

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

  下面我們對DataOutputStream流及其成員方法進行分析:

  2.1.1. DataOutputStream流

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

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

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

  2.1.2.

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

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

  Big Endian格式:

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

  1 2 3 4

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

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

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

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

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

  使用writeInt方法可以寫一個4-byte的int值v到輸出流,其字節(jié)順序為:

  (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é)順序為Big Endian格式,標準的“網(wǎng)絡字節(jié)順序”。

  但是在實際工作中輸出流采用DataOutputStream.readInt(int)方法時寫數(shù)據(jù)出錯,需要自己手動按照以上所說的對需要寫的v值進行轉(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流對于Java各個基本數(shù)據(jù)類型都相應地提供了“讀”方法,如readShort和readInt等,因此當進行進程間通信(sockect通信)時,我們總是優(yōu)先考慮使用DataInputStream流。

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

  但并非完美,特別是與不同語言的應用程序進行通信時(如C)。

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

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

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

  Type Java C

  long 8-Byte 4-Byte

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

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

  Type Java C

  byte 1-Byte N/A

  char 2-Byte 1-Byte

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

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

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

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

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

呵呵 我也很詫異“

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

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

“。。。但如果因為它是"一邊變換一邊執(zhí)行", 就將其當作解釋語言……只能說你看到表象卻沒抓住本質(zhì)。”

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

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

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

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

Compilation and Interpretation

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

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

點擊查看大圖

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

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

 

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

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

點擊查看大圖

書中的原文:”如果原始階段的翻譯器比較基本,我們就說這個語言是“解釋的”。如果翻譯器很復雜,我們就說這一語言是“編譯的”,F(xiàn)在兩者的區(qū)分變得有些模糊了,因為“基本 ”和“復雜”都是修飾性術語,也因為完全可能出現(xiàn)用一個編譯器(復雜的翻譯流程)生成代碼,而后又由一個復雜的虛擬機(解釋器)執(zhí)行。對于最后這種情況,如果翻譯器對程序做了徹底的分析(而不是做某種“機械的”變換),而且有關的中間語言程序與源程序并沒有很強的相似性,我們還是說這個語言是編譯的。這兩種特征 ----徹底的分析和非平凡的變換-----是刻畫編譯形式的標志性特征。“

根據(jù)以上標準,首先CSC只是對C#到IL做”機械“的翻譯,而且C#和IL之間有很強的相似性,因為兩者的程序代碼幾乎可以100%相互轉(zhuǎn)換(比如reflector可以將C#反編成IL,也可以將IL反編為C#)。您認為呢?

PS:再者某些人認為的ngen和cache程序集其實也是支持C#是解釋語言的結(jié)論,因為編譯型語言因為性能的天然因素是不須要這些手段的。也許我是錯的,請您不吝賜教,感激涕零.本人禁止了不負責任的匿名評論,請大家海涵。

]]>
主站蜘蛛池模板: 永修县| 井研县| 宁晋县| 仪陇县| 拉孜县| 清涧县| 和顺县| 康平县| 鹤壁市| 华宁县| 鲁甸县| 什邡市| 棋牌| 麟游县| 确山县| 凤城市| 五大连池市| 长岭县| 江安县| 乌鲁木齐县| 平原县| 邛崃市| 韶山市| 尚义县| 佛冈县| 隆昌县| 尖扎县| 驻马店市| 枣庄市| 边坝县| 古蔺县| 余姚市| 新疆| 禹州市| 冕宁县| 两当县| 阿拉善盟| 黄浦区| 宁武县| 临西县| 伊宁县|