亚洲精品99久久久久中文字幕,亚洲国产综合精品中文第一区,亚洲欧美精品一中文字幕http://www.bjzhda.cnzh-cn曙海教育集團論壇http://www.bjzhda.cnRss Generator By Dvbbs.Netofficeoffice@126.comimages/logo.gif曙海教育集團論壇Visual C++ 1.0:C++編譯器的終結者http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=63&ID=2446&Page=1wangxinxin2010-12-10 15:34:57
  Visual C++的發展與C/C++語言、Windows的歷程是分不開的。

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

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

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

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

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

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

  編輯器之爭

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

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

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

  自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的開發工具市場。恰逢Borland C/C++ 3.1的幕后支柱Eugene Wang剛好和Philippe Kahn鬧翻,離開了Borland。Symantec重金邀請Eugene Wang,1993年左右,Symantec推出了第一個Symantec C/C++版本,立刻便獲得了市場的好評。Symantec C/C++不斷完善,以最完美的、先進的集成開發環境獲得市場的高度認同。

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

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

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

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

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

  隨后,Windows 3.0出現了。Windows 3.0尤其是3.1,為個人計算機引進了真正的IDE時代。但是,Microsoft卻把精力更多地集中在C編譯器的內部支持上,而不是把它的界面升級到一個新的時代。盡管如此,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位的支持,但它僅用來創建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還增加了一些新類,但主要是集中在界面的改善上,并提供一個更好的在線幫助系統、更高級的宏能力和對在開發者組內進行類和其它代碼共享的支持。5.0中還合并了Active Template Library(ATL),并顯著地改善了編譯器優化代碼的能力。

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

  2000年7月,在PDC(Professional Developers Conference)會議上,Microsoft宣布啟動.NET方案,推出了一個全新的開發平臺Visual Studio.NET,這是Microsoft技術方向的重大轉變。在這個平臺上,包括了Visual C++、Visual Basic、Visual FoxPro和C#等開發工具。
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發布。Visual Studio .NET 2003 包含 Windows .NET Framework 的一個增強版本,并將移動和嵌入式設備,如 Pocket PC 和其他采用 Microsoft Windows CE .NET 操作系統的設備,帶入了 .NET。

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

  MFC和Visual C++

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

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

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

  AFX不得不重新做所有的一切,他們所創建的新的應用程序框架是一套擴展的C++類,它封裝和映射了Windows API,這就是MFC的前身。過去的AFX小組也變成了MFC小組。最終,MFC的第一個公開版本于1992年3月隨Microsoft C/C++ 7.0一起推出。那時距Windows 3.1發布尚有好幾個月。在MFC 1.0中還沒有文檔/視結構,但有類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中,增加了對文檔/視結構、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所取得的成功和它所產生的影響。

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

 

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

 

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

 

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

 

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

 

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

 

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

 

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

 

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

 

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

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

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

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

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

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

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

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

  Visual C++2010 新特性

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

  (1)Ribbion界面設計可視化

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

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

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

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

  3. 隨即打開Windows 窗體設計器,出現Form1 窗體

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

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

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

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

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

 對話框

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

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

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

  3. 使用 ClassWizard 給新創建的 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. 根據掌上電腦的屏幕面積調整該對話框的大小,使之能在掌上電腦中正確顯示。建議可以設為 196 x 47 象素大小;

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

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

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

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

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

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 按鈕時,進度控件的值要開始增長。在增長結束時,還要顯示一個消息框。下列代碼完成上述任務:

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

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


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

]]>
C和C++語言學習總結http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=63&ID=2441&Page=1wangxinxin2010-12-10 15:15:351、if,for,switch,goto
2、#define,const
3、文件拷貝的代碼,動態生成內存,復合表達式,strcpy,memcpy,sizeof
4、函數參數傳遞,內存分配方式,內存錯誤表現,malloc與new區別
5、類重載、隱藏與覆蓋區別,extern問題,函數參數的缺省值問題,宏代碼與內聯函數區別
6、構造和析構的次序,String函數定義


具體實現:
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:
執行效率問題:
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的數據類型可以是int,char,long,unsigned int,bool.
variable必須是整數或者強制為整數,由于char實際上是ASCII碼,所以也可以.
c不可以是double,float,char*.

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

error:
    ...


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

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

當是輸入參數時,不需要是void Func(const A a),void Func(A a),可以是void Func(A& a)或void Func(const A& a)
不用const A a,A a的原因是函數的效率比較低,因為函數體內將產生A類型的臨時對象用于復制參數a,而臨時對象的構造、復制和析構過程都需要消耗時間
最好用const A&a的原因是A&a中的a可以被改變,A&a和const A&a的好處在于都不會產生臨時對象,效率高;

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

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

動態生成內存的代碼
------------------------------------------
正確代碼:
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); // 注意參數是&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 是數學表達式而不是程序表達式
并不表示
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位操作系統中,基本數據類型
類型                  字節長度
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位操作系統中,定義或函數中的大小
char a[]="hello";
char b[100];
char *p=a;
類型                  字節長度
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語言及其開發工具 (2)http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=63&ID=2440&Page=1wangxinxin2010-12-10 15:13:24在Java中,對變量和方法的訪問控制是通過訪問修飾符來實現的。Java定義了4種
訪問級別:公共(public)、受保護(protected)、私有(private)和友好(friendly)。
公共類型的方法及變量可從任意類進行訪問;受保護類型的方法及變量只能從當前
類及其子類訪問;私有類型的方法及變量則只能從當前類訪問。如果未給出這三種
類型中任意一種的顯式說明 ,表明相應的方法或變量屬于"友好"類型,從而可由屬
于同一"包"(package)內的所有類進行訪問。在Java內,"包"是一個單獨的編譯單
位,它是具有某種共性的類所組成的集合。通過定義包這個單位,可實現相關對象
之間的相互訪問,同時把這些對象與包之外的其它對象隔離。 

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

2. 與C++的差別 

盡管C++程序員可以相對容易地掌握Java編程,但他們仍然必須克服從C++帶來的一
些舊習慣。Java取消了C++中的如下特性或功能: 

·結構或指針 ·#define語句 

·指針 ·多重繼承 

·獨立的函數 ·GOTO語句 

·操作符重載 ·自動類型轉換 

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

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

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

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

3. 內存管理和線索 

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

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

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

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

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

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

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

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

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

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

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

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

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

    內存管理

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

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

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

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

    資源管理

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

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

    因為必須要調用一個方法來釋放資源,由此帶來的問題是,現在更難編寫"全無異常"的代碼了。因為異常隨時都可能發生,你不可能只是簡單地在一段代碼后,放置一個對對象的Dispose方法的調用,這樣做的話,就必須要冒資源泄漏的風險。在C#中解決這個問題的辦法是,使用try-finally塊和using語句,在面對異常時,可提供一個更可靠的辦法來調用Dispose方法。有時,構造函數也會使用這種方法,但一般的情況是,你必須要記住手工編寫它們,如果忘記了,生成的代碼可能會存在一個悄無聲息的錯誤。對缺乏真正析構函數的語言來說,是否需要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++來說,情節也非常類似,也需要使用一個try-finally語句,但其是Microsoft對C++的擴展。雖然很容易編寫一個簡單的Using模板類來包裝GCHandle,并在模板類的析構函數中調用托管對象的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)); }
]]>
目前主流開發技術的分析和總結http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=63&ID=2437&Page=1wangxinxin2010-12-10 15:09:35
  桌面應用程序框架:MFC、VCL、QT、JavaAWTSWING、.Net

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

  開發工具:VisualBasic、Delphi、VisualC++、C++Builder、VisualC#

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

  *桌面應用程序框架:MFCVCL

  *企業應用程序框架:WindowsDNAJ2EE.Net

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

  2.1 程序設計語言

  2.1.1 C++語言的演進

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

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

  對=的重載成員轉換函數拷貝構造函數轉化構造函數之間有什么區別和聯系呢?

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

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

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

  2.1.2 Java和C#

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

  2.1.3 Delphi

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

  2.2桌面應用程序框架

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

  2.2.1MFC

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

  2.2.2VCL

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

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

Java是完全面向對象的,這和C++不盡相同。盡管C++被認為是一種面向對象的語言,但它仍然支持過程式程序設計風格。Java則不然,它要求程序員采用完全面向對象的編程技術 ,從而消除了由于混用兩種相同的編程風格而導致的種種問題。另一方面,Java的"外觀"和 "感覺"和C++又有著很多相似之處。Java消除了C和C++中的冗余以及所有過程式的編程風格 ,并且不再支持指針數據類型,同時增加了數組的自動邊界檢查和自動內存垃圾搜集,并且把數組封裝到類結構內,從而有助于開發分布計算環境下的應用程序。 

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

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

1.Java 的面向對象特征 

面向對象技術的關鍵在于封裝、繼承和動態聯編,下面就談談Java是如何支持這些關鍵特性的。 

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

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

當然,在個別情況下(對某些面向對象的語言而言),編程人員也可以直接訪問實例變量 ,但這并不是一個值得推薦的做法,因為它違背了面向對象的初衷。 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  VC提供了兩種宏記錄的方法:正常宏記錄和快速宏記錄。
快速宏記錄則可以快速記錄你的一些動作,而不需要命名、描述或者編輯這個宏,但是只可以保存一個,重新記錄將刪掉原來的快速宏。記錄快速宏的簡單過程如下:(1)選擇Tools菜單里的Record Quick Macro命令;(2)執行需要記錄的動作,在執行動作的過程中可以使用宏記錄器工具條上的Pause暫停按鈕來臨時中斷記錄或者繼續記錄;(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)執行需要記錄的動作,中間可以點擊Pause按鈕暫停或者繼續;(6)點擊Stop按鈕完成錄制,這時候VC將打開宏文件,并且把光標停在宏的起始點,你可以對宏進行檢查或者編輯。

圖1
  也可以往一個新的或者已有的宏文件里添加代碼,直接手工寫一個宏。步驟如下:(1)選擇Tools菜單的Macro命令打開宏管理器;(2)選擇宏文件或者新建宏文件;(3) 在Macro Name框里寫入宏的名字;(4)點擊Edit按鈕;(5)在Add Macro對話框里寫入宏的描述,點擊OK按鈕,VC將打開宏文件,在文件的尾部為新的宏創建一個架子-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宏,數量看需要而定。宏文件的一般格式是:開始是對這個文件的一些描述,然后就是每個宏的具體定義。

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

圖2
  有了VBScript宏,只要運行它即可以自動幫你完成所需要的操作啦!如果需要經常運行某個宏,那么可以為這個宏分配一個工具條按鈕或者熱鍵,這樣就可以通過點擊按鈕或者按熱鍵方便地運行這個宏了。分配按鈕的具體設置是:(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集成開發環境的功能,美觀、改造VC的界面,但是它們是有區別的。主要的區別當然在于:VBScript宏是使用VBScript語言寫的過程,而VC插件則是使用VC或者Visual Basic開發的COM構件。
開發VBScript宏比開發插件容易多了。生成一個VBScript宏只需要記錄宏、增加一些代碼(需要的話),然后運行就可以了。而生成一個插件需要VC來編寫代碼,編譯成DLL,然后與VC的集成開發環境連接(安裝插件),才能使用它提供的功能。
VBScript宏在功能上弱于插件。在宏里面,只能夠使用VBScript語言,只能訪問VC集成開發環境的對象;而插件則可以使用更多的語言(VC、VB),不僅能使用VC集成開發環境的對象,還可以使用整個計算機系統的資源。例如,宏里面與用戶交互只能使用VBScript提供的兩個對話框InputBox和MsgBox,而插件則可以使用任何形式的對話框。

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

圖4

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

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

  接著,需要創建一個插件的項目。使用VC的插件向導,向導將自動創建一個項目。如果使用VB來開發插件,最好以一個例子為基礎。

  項目創建了以后,就需要編寫代碼了。如果使用了VC的插件向導或者以VB的一個例子為基礎的話,那么大部分代碼已經有了,你只需要加入具體處理的一些代碼即可。

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

  VC 5.0以上的版本專門為插件的開發提供了一個插件向導。可以使用這個向導輕松、快速地生成插件的基本代碼,然后根據自己的需要進行修改。使用VC的插件向導進行插件開發的步驟如下:
首先,設計插件。接著,使用插件向導生成新的插件項目:(1)選擇File菜單的New命令;(2)在New對話框里,選擇Projects頁簽;(3)在窗口里選擇Developer Studio Add-in Wizard,在Project Name框里填入項目的名字,然后點擊OK;(4)這時進入插件向導(見圖5),為插件填寫名字和描述;如果插件需要工具條按鈕,則選上Provides a toolbar選項;如果插件需要處理VC集成開發環境對象的事件,則選上Responds to Developer Studio events選項,向導將為每個事件添加一個代碼框架,你必須為需要的事件提供具體的處理;點擊OK;(5)在彈出的New Project Information對話框里檢查向導即將生成的文件及項目目錄,確認正確后點擊OK就生成插件項目了。

圖5
然后,定制插件的功能或者增加新的功能。插件向導自動生成了添加一個功能到VC集成開發環境的代碼,但是如果你需要定制或者添加更多的功能的話,則要修改代碼,這個與普通應用開發是一樣的。修改需要使用到Application對象的三個方法:使用AddCommand方法添加一個功能;使用AddCommandBarButton方法添加一個工具條按鈕;使用AddKeyBinding方法來添加一個熱鍵。具體的做法請參照VC插件開發的幫助。

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

圖6

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

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

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

1.1語言特性的差異

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

1.1.1字節順序的差異

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

十六進制表示

0x00004E20

Windows內存表示

20 4E 00 00

Unix內存表示

00 00 4E 20

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

?         網絡通信時

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

?         文件存儲和讀取時

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

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

1.  數字轉換成字符傳進行交互

2.  協商一個同意的字節順序,根據自己平臺的字節順序還原數據

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


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

1.1.2變量的作用域差異

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

在C++的開發過程中,我們經常會有這樣的用法:

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

       {

              …

       }

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

       {

              …

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

II

              {

I

                     …

              }

              …

              …

       }


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

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循環中變量i沒有定義。相反代碼B在Solaris下可以正常編譯,而在Windows下面編不過去,提示第二個for循環中變量i重復定義。

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

C:

int i = 0;

if(cond)

{

       …

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

       {

              …

       }

       …

}

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

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

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

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

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

 

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

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

 

 

1.    基本概念

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

void __cdecl Your_Entry (void);

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

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

 

// VC++ Entry point

void MyEntry (void);

{

{

 

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

 

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

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

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

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

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

 

屏幕會提示順利設置了vc的環境變量。

 

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

d:\

cl /c test0.c /nologo

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

l         然后用下面的命令連接

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

不出什么意外的話,在D分區上應該有一個test0.exe文件,雙擊它發現什么也沒有出現。但是,其實它是一個不折不扣的Win32應用程序。你可以用相應工具來測試它,可以發現在入口點處是幾個符合C函數調用規則的幾個壓棧、數據轉移、和出棧指令。

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

 

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

 

2.    Microsoft C/C++ Runtime Library

有了上面這些基礎,我們接著再看一看Microsoft C/C++ Runtime Library在入口點處都作了些什么。我這里給出的代碼是經過篩選的,只是為了說明問題,這些代碼在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);

}

 

上面的代碼經過篩選,它用于多線程下,普通的多字符集C運行時。我稍微解釋一下代碼的含義,它完成以下任務:

l         獲取操作系統的版本信息,用于以后的操作;

l         然后初始化進程堆棧;

l         獲取命令行,獲取和設置環境變量;

l         C運行時內部變量的初始化;

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

l         調用ExitProcess函數退出應用程序,退出代碼是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.hufushizhe.com/bbs/dispbbs.asp?BoardID=63&ID=2430&Page=1wangxinxin2010-12-10 14:48:11
0 簡介

C語言及其典型實現被設計為能被專家們容易地使用。這門語言簡潔并附有表達力。但有一些限制可以保護那些浮躁的人。一個浮躁的人可以從這些條款中獲得一些幫助。


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


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


1 詞法缺陷

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


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


if(x > big) big = x;


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


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


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


1.1 = 不是 ==

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


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


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


if(x = y)
foo();


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


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


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


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


if(x = y)
foo();


改寫為:


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


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


1.2 & 和 | 不是 && 和 ||

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


1.3 多字符記號

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


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


y = x/*p /* p 指向除數 */;


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


y = x / *p /* p 指向除數 */;


或者干脆是


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


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


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


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中的意義完全不同,在一些混亂的上下文中它們會導致奇怪的結果而不是錯誤消息。


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


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


printf("Hello world\n");


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


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


printf('\n');


來代替


printf("\n");


通常會在運行時得到奇怪的結果。


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

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

  1.1. 使用的語言

  Client端:Java,JVM(JDK1.3)

  Server端:C,UNIX(Sun Solaris)

  1.2. 討論范圍

  數據發送:只涉及到Java中int整型系列的討論,包括byte,short,int。

  數據接受:涉及到byte,short,int,long,float,double,char。

  1.3.Java與C的數據類型的比較

  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. 實現

  輸出流:使用OutputStream流發送數據到C程序端。

  輸入流:使用DataInputStream流從C程序端接受數據

  2.1. 數據發送

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

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

  2.1.1. DataOutputStream流

  DataOutputStream流實現了接口DataOutput。

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

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

  2.1.2.

  網絡字節順序

  規定:網絡上傳輸的數據統一采用Big Endian格式(即“高字節在前”),我們稱之為“網絡字節順序”(network byte order)。

  Big Endian格式:

  高字節 低字節

  1 2 3 4

  Byte[0] byte[1] byte[2] byte[3]輸出緩沖區

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

  2.1.3. 數據發送:手動字節轉換 / writeInt方法

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

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

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

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

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

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

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

  這樣的字節順序為Big Endian格式,標準的“網絡字節順序”。

  但是在實際工作中輸出流采用DataOutputStream.readInt(int)方法時寫數據出錯,需要自己手動按照以上所說的對需要寫的v值進行轉換(通過移位完成),轉換的代碼如下所示,可參見程序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. 數據接收

  同數據發送相同,由于DataInputStream流對于Java各個基本數據類型都相應地提供了“讀”方法,如readShort和readInt等,因此當進行進程間通信(sockect通信)時,我們總是優先考慮使用DataInputStream流。

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

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

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

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

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

  Type Java C

  long 8-Byte 4-Byte

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

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

  Type Java C

  byte 1-Byte N/A

  char 2-Byte 1-Byte

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

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

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

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

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

呵呵 我也很詫異“

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

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

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

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

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

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

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

Compilation and Interpretation

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

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

點擊查看大圖

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

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

 

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

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

點擊查看大圖

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

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

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

]]>
主站蜘蛛池模板: 亚洲区小说区图片区qvod| 国产女人高潮抽搐喷水免费视频| 久久精品人人爽人人爽快| 波多野结衣1区| 国产偷国产偷精品高清尤物| 99久久中文字幕伊人| 性一交一乱一伧老太| 久草资源站在线| 欧美交a欧美精品喷水| 免费看日b视频| 美女毛片免费看| 国产欧美一区二区精品久久久| a一级日本特黄aaa大片| 很黄很污的视频在线观看| 久热中文字幕在线精品免费 | 老司机深夜福利在线观看| 国产真实乱对白mp4| a级片视频在线观看| 宅男噜噜噜66网站| 久久久精品久久久久特色影视| 最新国产三级久久| 亚洲第一区精品观看| 狼群视频在线观看www| 国产三级在线观看完整版| 韩国成人在线视频| 国产精品午夜小视频观看| juy031白木优子中文字幕| 少妇粉嫩小泬喷水视频| 久久久精品午夜免费不卡| 日韩免费福利视频| 亚洲国产精品久久久久秋霞影院| 欧美精品一区二区精品久久| 免费观看呢日本天堂视频| 精品国产自在现线看| 国产免费插插插| 18精品久久久无码午夜福利| 国产香港特级一级毛片| mm1313亚洲精品国产| 婷婷六月丁香午夜爱爱| 久久66久这里精品99| 日日噜狠狠噜天天噜AV|