久久99精品久久久久久琪琪,久久人人爽人人爽人人片亞洲,熟妇人妻无码中文字幕,亚洲精品无码久久久久久久

C++學習步驟

時間:2019-05-13 16:42:41下載本文作者:會員上傳
簡介:寫寫幫文庫小編為你整理了多篇相關的《C++學習步驟》,但愿對你工作學習有幫助,當然你在寫寫幫文庫還可以找到更多《C++學習步驟》。

第一篇:C++學習步驟

學習C++有那些步驟:

1。學習C++基本語法,參考書籍《C++程序設計》》錢能著,或《C++程序設計教程》DEITEL著,我看的是后者;

2。學習數(shù)據(jù)結構,參考書籍《數(shù)據(jù)結構C++語言描述——應用標準模板庫(STL)》William Ford著;

3。學習STL,參考書籍《C++標準程序庫》候捷譯;

4。學習模板,參考書籍《泛型編程與STL》候捷譯;

5。深入STL內(nèi)部,直到能自己寫出STL的源碼,參考書籍《STL源碼剖析》候捷譯;

6。學習I/O方面的知識,參考書籍《Standard C++ IOStream and Locales》;

7。重溫整個C++體系,參考書籍《C++ PRIMER》和《the c++ programming language》;

8。學習前人的技巧和方法,參考書籍〈effective c++>,;

9。再往上走,從宏觀上把握C++程序設計體系,參考書籍<設計模式>,《深入探索C++對象模型》,<大規(guī)模C++程序設計>;

接下來就可以分2條路走了:

一、偏理論的道路,考研,注意,不是考計算機系,是考數(shù)學系,學習集合論,圖論等知識,有一套書叫〈計算機程序設計藝術〉一至三卷,等你把他們都看完了,理解透了,就可以直接去微軟投簡歷了。

二、偏應用的道路,學習windows編程,學習MFC,COM,ATL,以及整個.NET體系。

第二篇:c++學習經(jīng)驗交流

曾經(jīng)因為自己的一些帖子在網(wǎng)上引起了大家對C++學習和使用的討論,再回想起自己接觸C++三年多,一年前鼓足勇氣重新開始再次學習的情景,現(xiàn)在的我心中多了幾份感慨,更多的是覺得自己學習的過程頗具普遍性,幾次想把自己的一些心得寫下來,對自己算是個總結和回顧,對別人即使談不上幫助但相信也能算是個學習C++的案例分析吧。但開始幾次提筆總是過于追求完美,想把所有的東西都寫下來,但幾次提筆和幾次放棄后,我終于打消了“完美”的這個想法,等一下還要和自己女朋友打電話,就這一個小時內(nèi),能說多少算多少吧,畢竟我是說出來寫下來了。

接觸C++是在99年,那個時候自己已經(jīng)有一些C語言的基礎了,剛開始會用的關鍵字比起C來說也許只多了Class吧,那個時候在學校,也學了VC++,寫了幾個很簡單的游戲程序,然后就因為很多瑣事沒有再在C++上有更多的深入,這也是我現(xiàn)在非常遺憾的事情,也許那個時候我能夠投入進去,現(xiàn)在應該是能頗有小成了。02年開始了一個新的里程,我自己有充足的來支配時間。就在那一年的暑假,開始了新的C++學習,我知道我以前的基礎對于學習C++來說,幾乎不會有什么更大的幫助,所以我選擇了重新開始,從IF….ELSE這樣的語法開始。選擇的第一本書是好友友情贈送的《C++ PRIMER》,當時我只是看了不到三天,我就沒有繼續(xù)看了,我知道這本書非常不錯,但是肯定不適合當時的我,因為從一開始就有過多的東西給我困惑,類,模板,重載……,這樣東西幾乎讓我放棄學習C++,因為我那個時候覺得自己C還是有一定功力的,就把C搞透對我來說那個時候也是個不錯的選擇,但畢竟C的內(nèi)涵無法讓我有更多的激情,重復的東西我向來就不喜歡。然后我開始考慮++這個兩種語言唯一的標示區(qū)別到底意味和蘊涵著什么?同時我開始考慮到底程序設計語言是什么?隨后我在圖書館借了本書《程序設計語言的概念和實現(xiàn)》,無論別人如何看待這本書讓我明白了很多,因為這本書最大的特點是抽象出了現(xiàn)代程序設計語言的各種語義和其中蘊涵的思想,讓我對語言本身這個概念有了更深刻的認識,讓我建立去了各種語言自身的不同的語法都代表實現(xiàn)一種對于所有語言都共有的語義,而一個富有邏輯的語義系列卻反映出了更一般的程序設計思想。在有了這個概念后,我接觸到了《C++設計與演化》這本書,在學習C++過程中這本書對我的幫助是最大的,這本書讓我明白了C++的設計理念和各種語言設施所代表的實現(xiàn)語義,既各種紛繁的C++語言特性都是為了實現(xiàn)某種功能并且在不違反C++設計哲學基礎上建立起來的。這樣的對于C++的宏觀基礎,讓我在以后的學習日子里受益非淺,而《C++設計與演化》這本書我也同時具有中英兩種版本,每當我對很多關于C++特性困惑的時候我都會把英文版(隨便炫耀一下,這本書上有B.S的親筆簽名:))拿出來,再好好的看看。就象前陣子對于C++的學習,可謂討論頗多,我自己也再次把這本書拿出來,評價自己所持有的觀點是否正確。從此我認為自己算是走入了學習C++正確道路。

10月B.S來到中國,那個時候的我對于C++可以說只是個完全初學者(呵呵,給大家舉個例子,那個時候我在杭州碰到了cber,他開始告訴我他的網(wǎng)名,我卻說你的姓名是什么?后來他寫下他的名字和聯(lián)系方式我卻還不知道我對面站著的是個C++頂尖高手,幸虧那個時候的我還和他合影了一張相片,這算是我比較明智的地方吧,至少沒有留下遺憾。)我雖然是個初學者,但我不認為我應該錯過這次和大師親密接觸的機會(尤其是在反復拜讀過他 的書和大部分論文后),自費來到杭州(其實也花了不少那里同學的錢:))聽了B.S在浙大的報告,我很早就去了,坐在第一排,整個報告會也是我第一個問問題,回想那個時候我的問題多少顯的幼稚,但我告訴自己無論自己現(xiàn)在怎么樣,這樣的機會一輩子也許不會有了,所以我始終保持了十分積極,B.S的答復十分詳細以至與我到后面就基本處于假聽的狀態(tài):》但B.S的大師風范卻讓我顛倒,從此對于C++的學習我也不再功利。

學習就是積累,期間我看過《C++編程思想》,又對C++有了更感性的了解,三個月后再次拿出《C++ PIRMER》,這個時候我已經(jīng)能非常明白LIPPMAN這本經(jīng)典大作的巧妙用心了,它絕對不是給初學者看的,但對于入門后完全的學習和理解C++效果卻十分明顯,從書的一開始就直接進入C++的主題,前面五章都用類設計一個數(shù)據(jù)結構,讓讀者完全明白了各種用戶定義類型所代表的抽象能力,然后直接進入第六章標準庫中的容器類,這樣的設計讓讀者十分清楚的建立容器和類這兩個C++中十分重要的概念,之后的學習自然是非常富有滿足感。以前學習編程的經(jīng)驗告訴我,寫程序才是學習的中心,所以并且我把《C++ PRIMER》中的大部分代碼都調(diào)試通過了,樣例的代碼連貫性也是這本書的最大的特點,而另外一大特點就是代碼沒有一個是可以直接通過的,都需要自己的調(diào)試,在調(diào)試這樣的代碼過程中更加深了我多C++的認識。不到兩個月的時間就把《C++ PRIMER》初看了一遍,加之在CSDN上面和大家的交流,感覺已經(jīng)建立起了對C++的完整的基本認識。

沒有看過《C++程序設計語言》,算是學過C++嗎?在我眼里,如果連語言的創(chuàng)作者的書都沒有讀過,如何去理解這本語言?去年12月我花了整整一個月把這本書好好的看了兩遍,唯一的感覺是這本書才是真正有資格稱為《C++編程思想》的。書和《C++ PRIMER》是完全的不同風格,后者告訴你的是完整C++的語法和其支持的語義。而前者是真正告訴你如何去用C++思考問題和編寫符合C++設計理念的代碼。你能明白C++的設計理念極其理念下的程序設計思路和代碼編寫規(guī)范。到今年元旦,感覺自己比起當初已經(jīng)是進步不小,所以沒有繼續(xù)看書,而是在寒假看了幾個大點規(guī)模的C++程序源代碼。

之后,我也讀了一些C++大家的作品,在這里需要提出來的是《C++標準程序庫》和《C++沉思錄》,前者寫作方式通俗易懂,但全書內(nèi)容卻十分豐富,對于學習標準庫可以說是最佳表現(xiàn)的作品。而后者,閱讀感覺和《C++程序設計語言》一樣,思想性非常強,讀這樣的書很累,腦子必須一直思考問題,思考作者里面提出的問題和他提出的解決方式。這本書最大的特點是非常直接的把C++語言的核心暴露出來-----三種抽象模型和極其語言設施本身對這三種抽象模型的支持。而《C++沉思錄》給我的更深層思考是什么才是運用C++最合理的方式,這也是后來我發(fā)帖說明自己對于C++的學習和使用的一些見解的原始思想來源。

再后來,自己慢慢的用C++實現(xiàn)了一些小程序,有的是書本上的,有的是自己想的,寫程序和調(diào)試的過程給我的感覺就是煩惱和滿足的交替過程也許就是這樣的反復過程才是程序員追求的。文章至此,多數(shù)記載了自己的歷程,對很多看到這里的讀者來說相信并沒有什么幫助,下面我非常直接的說出自己的學習C++感受,從前面我的經(jīng)歷大家都可以看的出來我不是什么高手,但我保證我下面寫的東西對于初學C++的是十分有幫助的,畢竟我剛剛走過那一段時的灰暗日子。

☆━━━━━━━━━━━━━━━━━━━━━━━━☆

即學即用就夠了,只是一門語言而已,而且同樣是語言,C++遠遠不如english重要。

☆━━━━━━━━━━━━━━━━━━━━━━━━☆

xor 的發(fā)言如下:

☆━━━━━━━━━━━━━━━━━━━━━━━━☆

其實我的建議是……,趁著中C++的毒不深,學Java先。

【 在 Ace(孤鴻·無雙)的大作中提到: 】

:學習C++重在理解其各種語言設施所代表的語義,以及C++所能表示的語義所代表的設計思想。首先從宏觀上入手,你需要明白的是C++是程序設計語言的本質(zhì)。在此我把C++最重要的性質(zhì)寫下來:C++是一門靜態(tài)類型檢查,基于C內(nèi)存模式,支持四種基本程序設計范型的語言。注意,這里說明了三個本質(zhì)特性,靜態(tài)說明了語言的類型檢查性質(zhì),基于C內(nèi)存模式告訴我們在C++中所有與內(nèi)存有關的操作都需要程序員自己來負責,這樣就帶來了很多設計程序時的需要注意的地方,而理解支持的四種基本范型卻是理解各種語言設施的基礎。然后記住C++的最大的一點設計哲學,也是其貫穿應用C++的一條本質(zhì),我引用《C++ PRIMER

☆━━━━━━━━━━━━━━━━━━━━━━━━☆

DonaldDuck 的發(fā)言如下:

☆━━━━━━━━━━━━━━━━━━━━━━━━☆

我看過的國人寫的書幾乎無一例外的老舊,C++標準化已有5年,居然還有一些書連STL都沒有提到,用這樣的書學到的也只能是老的C++你們也許會說,C++沒有這些內(nèi)容也能用,但我認為學技術就要向前看,這就和現(xiàn)在幾乎已經(jīng)沒用人用匯編寫應用軟件一個道理

第三篇:c++學習感想

C++的學習感想

06光信2班趙飛學號:060105021106記得大一下學期學習C語言的時候,我們都有這樣的困惑:課堂和教材的內(nèi)容基本上都能接受和理解,但真要實際動手編寫程序又感到腦袋一片空白而無從下手;其二,整個課程的所有內(nèi)容好不容易學完了,但對編寫實用化的程序,總感到眼花繚亂而無法下手,真?zhèn)€兒“欲起平之恨無力”。以至于在很長一段時間里在我的內(nèi)心里產(chǎn)生了一種學習C語言和c++的恐懼感,認為自己不是學C語言和c++的料,將來打死我也不會朝C語言和c++的方向發(fā)展。

到了大二后,看著我周圍的同學一個個地去參加計算機等級考試,拿了很多證書,一種羨慕感油然而生,決定也要像他們那樣多掌握些計算機方面的知識和技術。在我的視野里消失了一年多的C語言和c++又在我的心目中占有了一席之地。我開始決心學好它。恰逢本學期開設了選修課c++,我便毅然決然的報了名,在這門課程快要結束的時候,我也參加報名了計算機等級考試二級c++,看看我這個學期是否真的學了一些東西。

嶄新的21世紀,以現(xiàn)代電子信息產(chǎn)業(yè)為龍頭的全球經(jīng)濟一體化浪潮正席卷世界。此時的我們面臨著巨大的挑戰(zhàn)和機遇。而以IT技術為基礎的信息產(chǎn)業(yè)正深入到人類社會生活的方方面面,無論是生產(chǎn)制造、國防和科技等領域,還是第三產(chǎn)業(yè),計算機軟件現(xiàn)已成為擔任重任的核心力量,互聯(lián)網(wǎng)和軟件已成為新經(jīng)濟發(fā)展的重要基礎。因此,計算機軟件技術將是各類專業(yè)的大專生、本科生和研究生必備的基礎知識。

c++是著名的C語言的面向?qū)ο蟮臄U展。C語言最初設計時是作為一種面向系統(tǒng)軟件(操作系統(tǒng)Operating System和語言處理系統(tǒng))的開發(fā)語言,即是用來代替匯編語言的,但是由于它強大的生命力,在事務處理、科學計算、工業(yè)控制和數(shù)據(jù)庫技術等幾個方面都得到了廣泛的應用。即便進入到以計算機網(wǎng)絡為核心的信息時代,C語言仍然是作為通用的匯編語言使用,用以開發(fā)軟件、硬件結合的程序,如實時監(jiān)控程序、控制程序和設備驅(qū)動程序等。而c++是C語言的超集,它保留了C語言的所有組成部分而與之兼容,既可以做傳統(tǒng)的結構化程序設計,又能進行面向?qū)ο蟪绦蛟O計,也是當今世界上比較流行的程序設計語言。因此,學好c++對我們未來找工作大有裨益。

對于c++的學習,我有一些學習方法可以和大家分享,并認為通過這些方法可以使我們的編程技術獲得較大提高:

第一,是要加強實踐。C++程序設計語言是一門實踐性非常強的課程,若要真正掌握編程技術,使編程能力有較大的實質(zhì)性的提高,必須在認真聽課勤做筆記并讀懂教材的基礎上,通過上機實驗加強開發(fā)軟件的基本技能訓練。只有勤學苦練才能積累寶貴的編程經(jīng)驗,悟出編程技術的要領,牢固地掌握像Borland C++和Visual C++這樣優(yōu)秀的應用程序開發(fā)工具,快速沖向計算機應用領域的前沿。

其二,便是要學習掌握相關的程序庫(c++當然首先要掌c++標準程序庫)、相關的平臺技術(eg.NET),因為這些都是學習c++應掌握的輔助知識。在眾多的計算機學科中,有很多都出現(xiàn)了內(nèi)容的交叉現(xiàn)象。我們在學習c++的時候,如果能多看看有關這方面的書和查查相關的資料,對我們地學習也不無裨益。在這些程序庫和平臺技術上,我們還要鍛煉自己對目標問題的分析和歸納能力,做到能夠知其然且知其所以然,并能舉一反三,扎實、靈活和系統(tǒng)地掌握編程要點。

第三,便是要多看有關c++的資料書。選取一兩本自己能夠容易看懂的c++方面的書,進行精讀,和細讀。在學校的圖書館閱覽室有很多關于c++編程方面的書籍和資料,我們可以借幾本過來,對照著看看,對我們的學習是一定有幫助的。

最后,便是要持之以恒,鍥而不舍。羅馬的建成不是一日之功,任何學問的從熟練到精通都不是三天兩天的事。我們必須明白這個淺顯的道理。學習c++本身就是一項艱苦的歷程。浮躁的人、沒有忍性的人,是肯定學不好c++的。我們必須有狂熱的編程熱情,否則是很難堅持下去的。我們也必須學會自信,因為有些時候盡管我們花了相當多的時間和精力,我們也不能寫出一個程序。寫程序確實是很麻煩的,有時需要頓悟,有時需要漸悟。當我們真正學好了,學精通了,便會有“一覽眾山小” 的感慨了。我們就會因此而有一種莫言的自豪感。

如今美國的次貸危機引發(fā)的全球經(jīng)濟危機正襲擊著中國的沿海地區(qū),許多的工廠在經(jīng)濟危機的打擊下倒閉了,我們的就業(yè)壓力變得更大了。能否在未來的激烈競爭中脫穎而出、出人頭地完全要靠我們的真才實學。在軟件技術行業(yè),我們必須掌握好c++。通過對c++的學習達到精通后,我們還可以進一步學習Java、c#等,這時學習這些語言就相對較輕松了。其實只要我們能真正地把c++程序設計語言學精、學透,是不愁找不到工作的。

對我們光信息科學與技術專業(yè),通過學習c++程序設計語言,我們可以用它來進行光學計算、光學設計等,將那些不能通過手工計算設計的,可以通過c++編程算出來,尤其是關于卷積積分、傅里葉變換、拉普拉斯變換等關于高等數(shù)學方面的數(shù)學物理方程。還有Zemax的光路設計等。可以說,學好c++對我們學光信息科學這一專業(yè)的,意義非凡。

因此,我必須努力掌握好它,為自己能夠在以后找份好工作打下堅實的基礎。

2008.12.16

第四篇:C++“指針”學習建議

一.對于眾多人提出的c/c++中指針難學的問題做個總結:

指針學習不好關鍵是概念不清造成的,說的簡單點就是書沒有認真看,指針的學習猶如人在學習饒口令不多看多學多練是不行的,下面是兩個很經(jīng)典的例子,很多書上都有,對于學習的重點在于理解*x和x的理解,他們并不相同,*x所表示的其實就是變量a本身,x表示的是變量a在內(nèi)存中的地址,如果想明白可以輸出觀察cout<<*x“|”x;,當定義了int *x;后對x=&a的理解的問題。仔細閱讀和聯(lián)系下面的兩個例子我想指針問題就不是難點了!

#include main(){ int a,b;/* 定義a,b兩個整形變量用于輸入兩個整數(shù) */ int *point_1,*point_2,*temp_point;/* 定義三個指針變量 */ scanf(“%d,%d”,&a,&b);/* 格式化輸入a,b的值 */

point_1=&a;/* 把指針變量point_1的值指向變量a的地址 */ point_2=&b;/* 把指針變量point_2的值指向變量b的地址 */ if(a main(){ int a,b;/* 定義a,b兩個整形變量用于輸入兩個整數(shù) */ int *point_1,*point_2;/* 定義三個指針變量 */ scanf(“%d,%d”,&a,&b);/* 格式化輸入a,b的值 */

point_1 = &a;/* 把指針變量point_1的值指向變量a的地址 */ point_2 = &b;/* 把指針變量point_2的值指向變量b的地址 */

compositor(point_1,point_2);/* 調(diào)用自定義的排序涵數(shù),把a,b的地址傳遞給point_1和point_2 */ printf(“%d,%d”,a,b);/* 打印出a,b的值 */ } static compositor(p1,p2)int *p1,*p2;/* 定義形式參數(shù)p1,p2為指針變量 */ { int temp;/* 建立臨時存儲變量 */

if(*p1<*p2)/* 如果*p1

*p1 = *p2;/* 將*p1的值也就是a的值換成*p2的值也就是b的值,等價于a=b */ *p2 = temp;/* 將*p2的值也就是temp的值等價于b=temp */ } } /* 注意:此題與上題不同的是,直接改變了a于b的值達到真實改變的目的 */

二.C++指針使用方法解惑

“void ClearList(LNode * & HL)”

仔細看一下這種聲明方式,確實有點讓人迷惑。

下面以void func1(MYCLASS *&pBuildingElement); 為例來說明這個問題。在某種意義上,“*”和“&”是意思相對的兩個東西,把它們放在一起有什么意義呢?。為了理解指針的這種做法,我們先復習一下C/C++編程中無所不在的指針概念。我們都知道MYCLASS*的意思:指向某個對象的指針,此對象的類型為MYCLASS。Void func1(MYCLASS *pMyClass);

// 例如: MYCLASS* p = new MYCLASS; func1(p);

上面這段代碼的這種處理方法想必誰都用過,創(chuàng)建一個MYCLASS對象,然后將它傳入func1函數(shù)。現(xiàn)在假設此函數(shù)要修改pMyClass: void func1(MYCLASS *pMyClass){ DoSomething(pMyClass); pMyClass = // 其它對象的指針 }

第二條語句在函數(shù)過程中只修改了pMyClass的值。并沒有修改調(diào)用者的變量p的值。如果p指向某個位于地址0x008a00的對象,當func1返回時,它仍然指向這個特定的對象。(除非func1有bug將堆弄亂了,完全有這種可能。)

現(xiàn)在假設你想要在func1中修改p的值。這是你的權利。調(diào)用者傳入一個指針,然后函數(shù)給這個指針賦值。以往一般都是傳雙指針,即指針的指針,例如,CMyClass**。MYCLASS* p = NULL; func1(&p);

void func1(MYCLASS** pMyClass); { *pMyClass = new MYCLASS; ?? }

調(diào)用func1之后,p指向新的對象。在COM編程中,你到處都會碰到這樣的用法--例如在查詢對象接口的QueryInterface函數(shù)中: interface ISomeInterface { HRESULT QueryInterface(IID &iid, void** ppvObj); ?? };

LPSOMEINTERFACE p=NULL;

pOb->QueryInterface(IID_SOMEINTERFACE, &p);

此處,p是SOMEINTERFACE類型的指針,所以&p便是指針的指針,在QueryInterface返回的時候,如果調(diào)用成功,則變量p包含一個指向新的接口的指針。

如果你理解指針的指針,那么你肯定就理解指針引用,因為它們完全是一回事。如果你象下面這樣聲明函數(shù): void func1(MYCLASS *&pMyClass); { pMyClass = new MYCLASS; ?? } 其實,它和前面所講得指針的指針例子是一碼事,只是語法有所不同。傳遞的時候不用傳p的地址&p,而是直接傳p本身:

MYCLASS* p = NULL;

func1(p);

在調(diào)用之后,p指向一個新的對象。一般來講,引用的原理或多或少就象一個指針,從語法上看它就是一個普通變量。所以只要你碰到*&,就應該想到**。也就是說這個函數(shù)修改或可能修改調(diào)用者的指針,而調(diào)用者象普通變量一樣傳遞這個指針,不使用地址操作符&。

至于說什么場合要使用這種方法,我會說,極少。MFC在其集合類中用到了它--例如,CObList,它是一個Cobjects指針列表。

Class CObList : public Cobject { ??

// 獲取/修改指定位置的元素

Cobject*& GetAt(POSITION position); Cobject* GetAt(POSITION position)const; };

這里有兩個GetAt函數(shù),功能都是獲取給定位置的元素。區(qū)別何在呢?

區(qū)別在于一個讓你修改列表中的對象,另一個則不行。所以如果你寫成下面這樣: Cobject* pObj = mylist.GetAt(pos);

則pObj是列表中某個對象的指針,如果接著改變pObj的值: pObj = pSomeOtherObj;

這并改變不了在位置pos處的對象地址,而僅僅是改變了變量pObj。但是,如果你寫成下面這樣: Cobject*& rpObj = mylist.GetAt(pos);

現(xiàn)在,rpObj是引用一個列表中的對象的指針,所以當改變rpObj時,也會改變列表中位置pos處的對象地址--換句話說,替代了這個對象。這就是為什么CObList會有兩個GetAt函數(shù)的緣故。一個可以修改指針的值,另一個則不能。注意我在此說的是指針,不是對象本身。這兩個函數(shù)都可以修改對象,但只有*&版本可以替代對象。

在C/C++中引用是很重要的,同時也是高效的處理手段。所以要想成為C/C++高手,對引用的概念沒有透徹的理解和熟練的應用是不行的。

三.數(shù)據(jù)指針

在C/C++語言中一直是很受寵的;幾乎找不到一個不使用指針的C/C++應用。用于存儲數(shù)據(jù)和程序的地址,這是指針的基本功能。用于指向整型數(shù),用整數(shù)指針(int*);指向浮點數(shù)用浮點數(shù)指針(float*);指向結構,用對應的結構指針(struct xxx *);指向任意地址,用無類型指針(void*)。

有時候,我們需要一些通用的指針。在C語言當中,(void*)可以代表一切;但是在C++中,我們還有一些比較特殊的指針,無法用(void*)來表示。事實上,在C++中,想找到一個通用的指針,特別是通用的函數(shù)指針簡直是一個“不可能任務”。

C++是一種靜態(tài)類型的語言,類型安全在C++中舉足輕重。在C語言中,你可以用void*來指向一切;但在C++中,void*并不能指向一切,就算能,也失去了類型安全的意義了。類型安全往往能幫我們找出程序中潛在的一些BUG。

下面我們來探討一下,C++中如何存儲各種類型數(shù)據(jù)的指針。

C++指針探討

(一)數(shù)據(jù)指針 沐楓網(wǎng)志

1.數(shù)據(jù)指針

數(shù)據(jù)指針分為兩種:常規(guī)數(shù)據(jù)指針和成員數(shù)據(jù)指針

1.1 常規(guī)數(shù)據(jù)指針

這個不用說明了,和C語言一樣,定義、賦值是很簡單明了的。常見的有:int*, double* 等等。

如:

int value = 123;int * pn = &value;

1.2 成員數(shù)據(jù)指針

有如下的結構: struct MyStruct { int key;int value;};

現(xiàn)在有一個結構對象: MyStruct me;MyStruct* pMe = &me;

我們需要 value 成員的地址,我們可以: int * pValue = &me.value;//或

int * pValue = &pMe->value;

當然了,這個指針仍然是屬于第一種范籌----常規(guī)數(shù)據(jù)指針。

好了,我們現(xiàn)在需要一種指針,它指向MyStruct中的任一數(shù)據(jù)成員,那么它應該是這樣的子: int MyStruct::* pMV = &MyStruct::value;//或

int MyStruct::* pMK = &MyStruct::key;

這種指針的用途是用于取得結構成員在結構內(nèi)的地址。我們可以通過該指針來訪問成員數(shù)據(jù): int value = pMe->*pMV;// 取得pMe的value成員數(shù)據(jù)。

int key = me.*pMK;// 取得me的key成員數(shù)據(jù)。

那么,在什么場合下會使用到成員數(shù)據(jù)指針呢?

確實,成員指針本來就不是一種很常用的指針。不過,在某些時候還是很有用處的。我們先來看看下面的一個函數(shù): int sum(MyStruct* objs, int MyStruct::* pm, int count){ int result = 0;for(int i = 0;i < count;++i)result += objs[i].*pm;return result;}

這個函數(shù)的功能是什么,你能看明白嗎?它的功能就是,給定count個MyStruct結構的指針,計算出給定成員數(shù)據(jù)的總和。有點拗口對吧?看看下面的程序,你也許就明白了:

MyStruct me[10] = { {1,2},{3,4},{5,6},{7,8},{9,10},{11,12},{13,14},{15,16},{17,18},{19,20} };int sum_value = sum(me, &MyStruct::value, 10);//計算10個MyStruct結構的value成員的總和: sum_value 值 為 110(2+4+6+8+ int sum_key = sum(me, &MyStruct::key, 10);//計算10個MyStruct結構的key成員的總和: sum_key 值 為 100(1+3+5+7+

+19)+20)也許,你覺得用常規(guī)指針也可以做到,而且更易懂。Ok,沒問題: int sum(MyStruct* objs, int count){ int result = 0;for(int i = 0;i < count;++i)result += objs[i].value;return result;}

你是想這么做嗎?但這么做,你只能計算value,如果要算key的話,你要多寫一個函數(shù)。有多少個成員需要計算的話,你就要寫多少個函數(shù),多麻煩啊。指針

四.C++指針使用

在下列函數(shù)聲明中,為什么要同時使用*和&符號?以及什么場合使用這種聲明方式?

void func1(MYCLASS *&pBuildingElement);論壇中經(jīng)常有人問到這樣的問題。

本文試圖通過一些實際的指針使用經(jīng)驗來解釋這個問題。

仔細看一下這種聲明方式,確實有點讓人迷惑。在某種意義上,“*”和“&”是意思相對的兩個東西,把它們放在一起有什么意義呢?。為了理解指針的這種做法,我們先復習一下C/C++編程中無所不在的指針概念。我們都知道MYCLASS*的意思:指向某個對象的指針,此對象的類型為MYCLASS。void func1(MYCLASS *pMyClass);

// 例如: MYCLASS* p = new MYCLASS;

func1(p);

上面這段代碼的這種處理方法想必誰都用過,創(chuàng)建一個MYCLASS對象,然后將它傳入func1函數(shù)。現(xiàn)在假設此函數(shù)要修改pMyClass: void func1(MYCLASS *pMyClass){ DoSomething(pMyClass);pMyClass = // 其它對象的指針 }

第二條語句在函數(shù)過程中只修改了pMyClass的值。并沒有修改調(diào)用者的變量p的值。如果p指向某個位于地址0x008a00的對象,當func1返回時,它仍然指向這個特定的對象。(除非func1有bug將堆弄亂了,完全有這種可能。)

現(xiàn)在假設你想要在func1中修改p的值。這是你的權利。調(diào)用者傳入一個指針,然后函數(shù)給這個指針賦值。以往一般都是傳雙指針,即指針的指針,例如,CMyClass**。MYCLASS* p = NULL;func1(&p);void func1(MYCLASS** pMyClass);{ *pMyClass = new MYCLASS;?? }

調(diào)用func1之后,p指向新的對象。在COM編程中,你到處都會碰到這樣的用法--例如在查詢對象接口的QueryInterface函數(shù)中:

interface ISomeInterface { HRESULT QueryInterface(IID &iid, void** ppvObj);?? };

LPSOMEINTERFACE p=NULL;pOb->QueryInterface(IID_SOMEINTERFACE, &p);

此處,p是SOMEINTERFACE類型的指針,所以&p便是指針的指針,在QueryInterface返回的時候,如果調(diào)用成功,則變量p包含一個指向新的接口的指針。

如果你理解指針的指針,那么你肯定就理解指針引用,因為它們完全是一回事。如果你象下面這樣聲明函數(shù): void func1(MYCLASS *&pMyClass);{ pMyClass = new MYCLASS;?? } 其實,它和前面所講得指針的指針例子是一碼事,只是語法有所不同。傳遞的時候不用傳p的地址&p,而是直接傳p本身:

MYCLASS* p = NULL;func1(p);在調(diào)用之后,p指向一個新的對象。一般來講,引用的原理或多或少就象一個指針,從語法上看它就是一個普通變量。所以只要你碰到*&,就應該想到**。也就是說這個函數(shù)修改或可能修改調(diào)用者的指針,而調(diào)用者象普通變量一樣傳遞這個指針,不使用地址操作符&。

至于說什么場合要使用這種方法,我會說,極少。MFC在其集合類中用到了它--例如,CObList,它是一個CObjects指針列表。

class CObList : public CObject { ??

// 獲取/修改指定位置的元素

CObject*& GetAt(POSITION position);CObject* GetAt(POSITION position)const;};這里有兩個GetAt函數(shù),功能都是獲取給定位置的元素。區(qū)別何在呢?

區(qū)別在于一個讓你修改列表中的對象,另一個則不行。所以如果你寫成下面這樣: CObject* pObj = mylist.GetAt(pos);

則pObj是列表中某個對象的指針,如果接著改變pObj的值: pObj = pSomeOtherObj;

這并改變不了在位置pos處的對象地址,而僅僅是改變了變量pObj。但是,如果你寫成下面這樣: CObject*& rpObj = mylist.GetAt(pos);

現(xiàn)在,rpObj是引用一個列表中的對象的指針,所以當改變rpObj時,也會改變列表中位置pos處的對象地址--換句話說,替代了這個對象。這就是為什么CObList會有兩個GetAt函數(shù)的緣故。一個可以修改指針的值,另一個則不能。注意我在此說的是指針,不是對象本身。這兩個函數(shù)都可以修改對象,但只有*&版本可以替代對象。

在C/C++中引用是很重要的,同時也是高效的處理手段。所以要想成為C/C++高手,對引用的概念沒有透徹的理解和熟練的應用是不行的。

五.新手學習之淺析c/c++中的指針

在學習c/c+過程中,指針是一個比較讓人頭痛的問題,稍微不注意將會是程序編譯無法通過,甚至造成死機。在程序設計過程中,指針也往往是產(chǎn)生隱含bug的原因。下面就來談談指針的應用以及需要注意的一些問題,里面也許就有你平時沒有注意到的問題,希望能幫助各位讀者理解好指針。

一、我們先來回憶一下指針的概念吧,方便下面的介紹

指針是存放地址值的變量或者常量。例如:int a=1;&a就表示指針常量(“&”表示取地址運算符,也即引用)。int *b,b表示的是指針變量(注意,是b表示指針變量而不是*b),*表示要說明的是指針變量。大家注意int *b[2]和int(*b)[2]是不同的,int *b表示一個指針數(shù)組,而int(*b)[2]表示含有兩個元素的int指針,這里要注意運算優(yōu)先級問題,有助于理解指針問題。在這里大概介紹基本概念就夠了,至于具體使用方法,如賦值等,很多書都有介紹,我就不多說了。

二、應用以及注意的問題

1、理解指針的關鍵所在——對指針類型和指針所指向的類型的理解

①、指針類型:可以把指針名字去掉,剩下的就是這個指針

例如: int *a;//指針類型為int *

int **a;//指針類型為int **

int *(*a)[8];//指針類型為 int *(*)[8]

②、指針所指向的類型:是指編譯器將把那一片內(nèi)存所看待成的類型。這里只要把指針聲明語句中的指針名字和名字右邊的“*”號去掉就可以了,剩下的就是指針所指向的類型。

我之所以把他們放在第一位,是因為弄清楚他們是學c/c++指針的重點,正確理解他們才能使你打好c/c++的編程基礎。

2、指針的應用——傳遞參數(shù)。

其實它可以相當于隱式的返回值,這就比return的方法更加靈活了,可以返回更多的值,看看下面的例子自然就明白了:

#include “iostream.h”

void example(int *a1,int &b1,int c1)

{

*a1*=3;

++b1;

++c1;

}

void main()

{

int *a;

int b,c;

*a=6;

b=7;c=10;

example(a,b,c);

cout <<“*a=”<<*a<

cout <<“b=”<

cout <<“c=”<

}

輸出:*a=18

b=8

c=10

注意到?jīng)]有,*a和b的值都改變了,而c沒有變。這是由于a1是指向*a(=6)的指針,也即與a是指向同一個地址,所以當a1指向的值改變了,*a的值也就改變了。在函數(shù)中的參數(shù)使用了引用(int &b1),b1是b的別名,也可以把它當作特殊的指針來理解,所以b的值會改變。函數(shù)中的參數(shù)int c1只是在函數(shù)中起作用,當函數(shù)結束時候便消失了,所以在main()中不起作用。

3、關于全局變量和局部變量的一個問題先不廢話了,先看看程序:

#include “iostream.h”

int a=5;

int *example1(int b)

{

a+=b;

return &a;

}

int *example2(int b)

{

int c=5;

b+=c;

return &b;

}

void main()

{

int *a1=example1(10);

int *b1=example2(10);

cout <<”a1=”<<*a1<

cout <<”b1=”<<*b1<

}

輸出結果:

a1=15

b1=4135

*b1怎么會是4135,而不是15呢?是程序的問題?沒錯吧?

由于a是全局變量,存放在全局變量的內(nèi)存區(qū),它一直是存在的;而局部變量則是存在于函數(shù)的棧區(qū),當函數(shù)example2()調(diào)用結束后便消失,是b指向了一個不確定的區(qū)域,產(chǎn)生指針懸掛。

下面是對example1()和example2()的反匯編(用TC++ 3.0編譯):

example1():

push bp;入棧

mov bp,sp mov ax,[bp+04];傳遞參數(shù)

add [00AA],ax;相加

mov ax,00AA;返回了結果所在的地址

..pop bp;恢復棧,出棧

ret;退出函數(shù)

example2():

push bp;入棧

mov bp,sp

sub sp,02

mov word ptr [bp-02],0005

mov ax,[bp-02];傳遞參數(shù)

add [bp+04],ax;相加

lea ax,[bp+04];問題就出在這里

..mov sp,bp

pop bp;恢復棧,出棧

ret;退出函數(shù)

對比之后看出來了吧?ax應該是存儲的是結果的地址。而在example2()中,返回的卻是[bp+04]的內(nèi)容,因此指針指向了一個不確定的地方,由此產(chǎn)生的指針懸掛。example1()中,ax返回了正確的結果的地址。

4、內(nèi)存問題:使用指針注意內(nèi)存的分配和邊界。使用指針過程中應該給變量一個適當?shù)目臻g,以免產(chǎn)生不可見的錯誤。請看以下代碼:

#include “iostream.h”

void main()

{

char *a1;

char *a2;

cin >>a1;

cin >>a2;

cout <<”a1=”<

cout <<”a2=”<

}

輸入:abc

123

輸出:

a1=123

a2=

Null pointer assignment

指針指向了“空”。解決辦法就是分配適當?shù)膬?nèi)存給這兩個字符串。修正后的代碼

如下:

#include “iostream.h”

void main()

{

char *a1;

char *a2;

a1=new char [10];

a2=new char [10];

cin >>a1;

cin >>a2;

cout <<”a1=”<

cout <<”a2=”<

delete(a1);注意,別忘了要釋放內(nèi)存空間

delete(a2);

}

到此就能輸出正確的結果了。分配了適當?shù)膬?nèi)存之后要注意釋放內(nèi)參空間,同時還應該注意不要超出所分配的內(nèi)存的大小,否則會有溢出現(xiàn)象產(chǎn)生,導致不可預料的結果。

5、關于特殊的指針——引用

引用有時候應用起來要比指針要靈活,用它做返回的時候是不產(chǎn)生任何變量的副本的這樣減小了內(nèi)存的占用,提高執(zhí)行的速度。引用使用起來要比指針好理解,比較直觀。當引用作為參數(shù)時,不會改變參數(shù)的地址,因此可以作為左值。

下面請看一個例子:

#include “iostream.h”

char ch[5]=”ABCD”;

char &example(int b)

{

return ch;

}

void main()

{

cout <<”ch=”<

example(2)=”c”;

cout<<”ch=”<

}

輸出結果:

ch=ABCD

ch=ABcD

在實際編程過程中,可以靈活地引用或指針,盡量提高程序的可讀性和執(zhí)行效率。

三、小結:

指針是學習c/c++的重點難點,主要原因是指針較為抽象,不容易理解。使用指針千萬要明白讓指針指向什么地方,如何讓指針指向正確的地方。在深入系統(tǒng)底層之中需要應用到大量的指針,因此需要理解好指針的基本概念,例如:指針類型和指針所指向的類型。平時應該對留心觀察,了解程序的工作過程,必要時候可以對程序進行反匯編,加深對指針的理解,這種方法同樣適合學別的編程方面的知識。

四、結束:

指針的應用是很廣泛的,利用指針可以做很多事情,要成為一個好的程序員,必須對指針有比較深刻的了解。寫本文的目的在于讓大家對指針有更深一層的了解,提高指針的應用能力,內(nèi)容大都是我在實際編程中遇到的問題。相信能給大家一定的幫助。

六.C++中關于指針入門的最好的文章

什么是指針?

其實指針就像是其它變量一樣,所不同的是一般的變量包含的是實際的真實的數(shù)據(jù),而指針是一個指示器,它告訴程序在內(nèi)存的哪塊區(qū)域可以找到數(shù)據(jù)。這是一個非常重要的概念,有很多程序和算法都是圍繞指針而設計的,如鏈表。

開始學習

如何定義一個指針呢?就像你定義一個其它變量一樣,只不過你要在指針名字前加上一個星號。我們來看一個例子:下面這個程序定義了兩個指針,它們都是指向整型數(shù)據(jù)。

int* pNumberOne;

int* pNumberTwo;

你注意到在兩個變量名前的“p”前綴了嗎?這是程序員通常在定義指針時的一個習慣,以提高便程序的閱讀性,表示這是個指針。現(xiàn)在讓我們來初始化這兩個指針:

pNumberOne = &some_number;

pNumberTwo = &some_other_number;

&號讀作“什么的地址”,它表示返回的是變量在內(nèi)存中的地址而不是變量本身的值。在這個例子中,pNumberOne 等于some_number的地址,所以現(xiàn)在pNumberOne指向some_number。如果現(xiàn)在我們在程序中要用到some_number,我們就可以使用pNumberOne。

我們來學習一個例子:

在這個例子中你將學到很多,如果你對指針的概念一點都不了解,我建議你多看幾遍這個例子,指針是個很復雜的東西,但你會很快掌握它的。

這個例子用以增強你對上面所介紹內(nèi)容的了解。它是用C編寫的(注:原英文版是用C寫的代碼,譯者重新用C++改寫寫了所有代碼,并在DEV C++ 和VC++中編譯通過!)

#include

void main()

{ // 聲明變量:

int nNumber;

int *pPointer;

// 現(xiàn)在給它們賦值:

nNumber = 15;

pPointer = &nNumber;

//打印出變量nNumber的值:

cout<<“nNumber is equal to :”<< nNumber<

// 現(xiàn)在通過指針改變nNumber的值:

*pPointer = 25;

//證明nNumber已經(jīng)被上面的程序改變

//重新打印出nNumber的值:

cout<<“nNumber is equal to :”<

}

通讀一下這個程序,編譯并運行它,務必明白它是怎樣工作的。如果你完成了,準備好,開始下一小節(jié)。

陷井!

試一下,你能找出下面這段程序的錯誤嗎?

#include

int *pPointer;

void SomeFunction();

{

int nNumber;

nNumber = 25;

//讓指針指向nNumber:

pPointer = &nNumber;

}

void main()

{

SomeFunction();//為pPointer賦值

//為什么這里失敗了?為什么沒有得到25

cout<<“Value of *pPointer: ”<<*pPointer<

}

這段程序先調(diào)用了SomeFunction函數(shù),創(chuàng)建了個叫nNumber的變量,接著讓指針pPointer指向了它。可是問題出在哪兒呢?當函數(shù)結束后,nNumber被刪掉了,因為這一個局部變量。局部變量在定義它的函數(shù)執(zhí)行完后都會被系統(tǒng)自動刪掉。也就是說當SomeFunction 函數(shù)返回主函數(shù)main()時,這個變量已經(jīng)被刪掉,但pPointer還指著變量曾經(jīng)用過的但現(xiàn)在已不屬于這個程序的區(qū)域。如果你還不明白,你可以再讀讀這個程序,注意它的局部變量和全局變量,這些概念都非常重要。

但這個問題怎么解決呢?答案是動態(tài)分配技術。注意這在C和C++中是不同的。由于大多數(shù)程序員都是用C++,所以我用到的是C++中常用的稱謂。

動態(tài)分配

動態(tài)分配是指針的關鍵技術。它是用來在不必定義變量的情況下分配內(nèi)存和讓指針去指向它們。盡管這么說可能會讓你迷惑,其實它真的很簡單。下面的代碼就是一個為一個整型數(shù)據(jù)分配內(nèi)存的例子:

int *pNumber;

pNumber = new int;

第一行聲明一個指針pNumber。第二行為一個整型數(shù)據(jù)分配一個內(nèi)存空間,并讓pNumber指向這個新內(nèi)存空間。下面是一個新例,這一次是用double雙精型:

double *pDouble;

pDouble = new double;

這種格式是一個規(guī)則,這樣寫你是不會錯的。

但動態(tài)分配又和前面的例子有什么不同呢?就是在函數(shù)返回或執(zhí)行完畢時,你分配的這塊內(nèi)存區(qū)域是不會被刪除的所以我們現(xiàn)在可以用動態(tài)分配重寫上面的程序:

#include

int *pPointer;

void SomeFunction()

{ // 讓指針指向一個新的整型

pPointer = new int;

*pPointer = 25;

}

void main()

{

SomeFunction();// 為pPointer賦值

cout<<“Value of *pPointer: ”<<*pPointer<

}

通讀這個程序,編譯并運行它,務必理解它是怎樣工作的。當SomeFunction調(diào)用時,它分配了一個內(nèi)存,并讓pPointer指向它。這一次,當函數(shù)返回時,新的內(nèi)存區(qū)域被保留下來,所以pPointer始終指著有用的信息,這是因為了動態(tài)分配。但是你再仔細讀讀上面這個程序,雖然它得到了正確結果,可仍有一個嚴重的錯誤。

分配了內(nèi)存,別忘了回收

太復雜了,怎么會還有嚴重的錯誤!其實要改正并不難。問題是:你動態(tài)地分配了一個內(nèi)存空間,可它絕不會被自動刪除。也就是說,這塊內(nèi)存空間會一直存在,直到你告訴電腦你已經(jīng)使用完了。可結果是,你并沒有告訴電腦你已不再需要這塊內(nèi)存空間了,所以它會繼續(xù)占據(jù)著內(nèi)存空間造成浪費,甚至你的程序運行完畢,其它程序運行時它還存在。當這樣的問題積累到一定程度,最終將導致系統(tǒng)崩潰。所以這是很重要的,在你用完它以后,請釋放它的空間,如:

delete pPointer;

這樣就差不多了,你不得不小心。在這你終止了一個有效的指針(一個確實指向某個內(nèi)存的指針)。下面的程序,它不會浪費任何的內(nèi)存:

#include

int *pPointer;

void SomeFunction()

{ // 讓指針指向一個新的整型

pPointer = new int;

*pPointer = 25;

}

void main()

{

SomeFunction();//為pPointer賦值

cout<<“Value of *pPointer: ”<<*pPointer<

delete pPointer;

}

只有一行與前一個程序不同,但就是這最后一行十分地重要。如果你不刪除它,你就會制造一起“內(nèi)存漏洞”,而讓內(nèi)存逐漸地泄漏。(譯者:假如在程序中調(diào)用了兩次SomeFunction,你又該如何修改這個程序呢?請讀者自己思考)

傳遞指針到函數(shù)

傳遞指針到函數(shù)是非常有用的,也很容易掌握。如果我們寫一個程序,讓一個數(shù)加上5,看一看這個程序完整嗎?:

#include

void AddFive(int Number)

{

Number = Number + 5;

}

void main()

{

int nMyNumber = 18;

cout<<“My original number is ”<

AddFive(nMyNumber);

cout<<“My new number is ”<

}

問題出在函數(shù)AddFive里用到的Number是變量nMyNumber的一個副本而傳遞給函數(shù),而不是變量本身。因此,“ Number = Number + 5” 這一行是把變量的副本加了5,而原始的變量在主函數(shù)main()里依然沒變。試著運行這個程序,自己去體會一下。要解決這個問題,我們就要傳遞一個指針到函數(shù),所以我們要修改一下函數(shù)讓它能接受指針:把'void AddFive(int Number)' 改成 'void AddFive(int*Number)'。下面就是改過的程序,注意函數(shù)調(diào)用時要用&號,以表示傳遞的是指針:

#include

void AddFive(int* Number)

{

*Number = *Number + 5;

}

void main()

{

int nMyNumber = 18;

cout 七.我眼中的指針--學習指針不可少的好文章

我眼中的指針--學習指針不可少的好文章

為初學者服務。這是我的帖子的宗旨。我也是個初學者(強調(diào)了無數(shù)遍了),我以我的理解把初學者覺得難懂的東西用淺顯的語言寫出來。由于小學時語文沒學好,所以竭盡全力也未必能達到這個目的。盡力而為吧。

指針是c和c++中的難點和重點。我只精通dos下的basic。c語言的其它各種特性,在basic中都有類似的東西。只有指針,是baisc所不具備的。指針是c的靈魂。

我不想重復大多數(shù)書上說得很清楚的東西,我只是把我看過的書中說得不清楚或沒有說,而我又覺得我理解得有點道理的東西寫出來。我的目的是:

1。通過寫這些東西,把我腦袋中關于c的模糊的知識清晰化。2。給初學者們一點提示。

3。賺幾個經(jīng)驗值。(因為貼這些東西沒有灌水之嫌啊)

第一章。指針的概念

指針是一個特殊的變量,它里面存儲的數(shù)值被解釋成為內(nèi)存里的一個地址。要搞清一個指針需要搞清指針的四方面的內(nèi)容:指針的類型,指針所指向的類型,指針的值或者叫指針所指向的內(nèi)存區(qū),還有指針本身所占據(jù)的內(nèi)存區(qū)。讓我們分別說明。先聲明幾個指針放著做例子: 例一:(1)int *ptr;(2)char *ptr;(3)int **ptr;(4)int(*ptr)[3];(5)int *(*ptr)[4];如果看不懂后幾個例子的話,請參閱我前段時間貼出的文?lt;<如何理解c和c++的復雜類型聲明>>。

1。指針的類型。

從語法的角度看,你只要把指針聲明語句里的指針名字去掉,剩下的部分就是這個指針的類型。這是指針本身所具有的類型。讓我們看看例一中各個指針的類型:(1)int *ptr;//指針的類型是int *(2)char *ptr;//指針的類型是char *(3)int **ptr;//指針的類型是 int **(4)int(*ptr)[3];//指針的類型是 int(*)[3](5)int *(*ptr)[4];//指針的類型是 int *(*)[4] 怎么樣?找出指針的類型的方法是不是很簡單?

2。指針所指向的類型。

當你通過指針來訪問指針所指向的內(nèi)存區(qū)時,指針所指向的類型決定了編譯器將把那片內(nèi)存區(qū)里的內(nèi)容當做什么來看待。從語法上看,你只須把指針聲明語句中的指針名字和名字左邊的指針聲明符 * 去掉,剩下的就是指針所指向的類型。例如:

(1)int *ptr;//指針所指向的類型是int(2)char *ptr;//指針所指向的的類型是char(3)int **ptr;//指針所指向的的類型是 int *(4)int(*ptr)[3];//指針所指向的的類型是 int()[3](5)int *(*ptr)[4];//指針所指向的的類型是 int *()[4] 在指針的算術運算中,指針所指向的類型有很大的作用。指針的類型(即指針本身的類型)和指針所指向的類型是兩個概念。當你對C越來越熟悉時,你會發(fā)現(xiàn),把與指針攪和在一起的“類型”這個概念分成“指針的類型”和“指針所指向的類型”兩個概念,是精通指針的關鍵點之一。我看了不少書,發(fā)現(xiàn)有些寫得差的書中,就把指針的這兩個概念攪在一起了,所以看起書來前后矛盾,越看越糊涂。

3。指針的值,或者叫指針所指向的內(nèi)存區(qū)或地址。

指針的值是指針本身存儲的數(shù)值,這個值將被編譯器當作一個地址,而不是一個一般的數(shù)值。在32位程序里,所有類型的指針的值都是一個32位整數(shù),因為32位程序里內(nèi)存地址全都是32位長。指針所指向的內(nèi)存區(qū)就是從指針的值所代表的那個內(nèi)存地址開始,長度為sizeof(指針所指向的類型)的一片內(nèi)存區(qū)。以后,我們說一個指針的值是XX,就相 當于說該指針指向了以XX為首地址的一片內(nèi)存區(qū)域;我們說一個指針指向了某塊內(nèi)存區(qū)域,就相當于說該指針的值是這塊內(nèi)存區(qū)域的首地址。

指針所指向的內(nèi)存區(qū)和指針所指向的類型是兩個完全不同的概念。在例一中,指針所指向的類型已經(jīng)有了,但由于指針還未初始化,所以它所指向的內(nèi)存區(qū)是不存在的,或者說是無意義的。

以后,每遇到一個指針,都應該問問:這個指針的類型是什么?指針指向的類型是什么?該指針指向了哪里? 4。指針本身所占據(jù)的內(nèi)存區(qū)。

指針本身占了多大的內(nèi)存?你只要用函數(shù)sizeof(指針的類型)測一下就知道了。在32位平臺里,指針本身占據(jù)了4個字節(jié)的長度。指針本身占據(jù)的內(nèi)存這個概念在判斷一個指針表達式是否是左值時很有用。

第二章。指針的算術運算

指針可以加上或減去一個整數(shù)。指針的這種運算的意義和通常的數(shù)值的加減運算的意義是不一樣的。例如: 例二:

1。char a[20];2。int *ptr=a;......3。ptr++;在上例中,指針ptr的類型是int*,它指向的類型是int,它被初始化為指向整形變量a。接下來的第3句中,指針ptr被加了1,編譯器是這樣處理的:它把指針ptr的值加上了sizeof(int),在32位程序中,是被加上了4。由于地址是用字節(jié)做單位的,故ptr所指向的地址由原來的變量a的地址向高地址方向增加了4個字節(jié)。

由于char類型的長度是一個字節(jié),所以,原來ptr是指向數(shù)組a的第0號單元開始的四個字節(jié),此時指向了數(shù)組a中從第4號單元開始的四個字節(jié)。我們可以用一個指針和一個循環(huán)來遍歷一個數(shù)組,看例子: 例三: 例三: int array[20];int *ptr=array;...//此處略去為整型數(shù)組賦值的代碼。...for(i=0;i<20;i++){(*ptr)++;ptr++; } 這個例子將整型數(shù)組中各個單元的值加1。由于每次循環(huán)都將

八.指針詳解

第一章。指針的概念

指針是一個特殊的變量,它里面存儲的數(shù)值被解釋成為內(nèi)存里的一個地址。

要搞清一個指針需要搞清指針的四方面的內(nèi)容:指針的類型,指針所指向的類型,指針的值或者叫指針所指向的內(nèi)存區(qū),還有指針本身所占據(jù)的內(nèi)存區(qū)。讓 我們分別說明。先聲明幾個指針放著做例子: 例一:(1)int*ptr;(2)char*ptr;(3)int**ptr;(4)int(*ptr)[3];(5)int*(*ptr)[4];

1。指針的類型。

從語法的角度看,你只要把指針聲明語句里的指針名字去掉,剩下的部分就是這個指針的類型。這是指針本身所具有的類型。讓我們看看例一中各個指針的類型:(1)int*ptr;//指針的類型是int*(2)char*ptr;//指針的類型是char*(3)int**ptr;//指針的類型是int**(4)int(*ptr)[3];//指針的類型是int(*)[3](5)int*(*ptr)[4];//指針的類型是int*(*)[4] 怎么樣?找出指針的類型的方法是不是很簡單?

2。指針所指向的類型。

當你通過指針來訪問指針所指向的內(nèi)存區(qū)時,指針所指向的類型決定了編譯器將把那片內(nèi)存區(qū)里的內(nèi)容當做什么來看待。從語法上看,你只須把指針聲明語句中的指針名字和名字左邊的指針聲明符 *去掉,剩下的就是指針所指向的類型。例如:

(1)int*ptr;//指針所指向的類型是int(2)char*ptr;//指針所指向的的類型是char(3)int**ptr;//指針所指向的的類型是int*(4)int(*ptr)[3];//指針所指向的的類型是int()[3](5)int*(*ptr)[4];//指針所指向的的類型是int*()[4] 在指針的算術運算中,指針所指向的類型有很大的作用。

指針的類型(即指針本身的類型)和指針所指向的類型是兩個概念。當你對C越來越熟悉時,你會發(fā)現(xiàn),把與指針攪和在一起的“類型”這個概念分成“指針的類型”和“指針所指向的類型”兩個概念,是精通指針的關鍵點之一。我看了不少書,發(fā)現(xiàn)有些寫得差的書中,就把指針的這兩個概念攪在一起了,所以看起書來前后矛盾,越看越糊涂。

3。指針的值,或者叫指針所指向的內(nèi)存區(qū)或地址。

指針的值是指針本身存儲的數(shù)值,這個值將被編譯器當作一個地址,而不是一個一般的數(shù)值。在32位程序里,所有類型的指針的值都是一個32位整數(shù),因為32位程序里內(nèi)存地址全都是32位長。指針所指向的內(nèi)存區(qū)就是從指針的值所代表的那個內(nèi)存地址開始,長度為sizeof(指針所指向的類型)的一片內(nèi)存區(qū)。以后,我們說一個指針的值是XX,就相當于說該指針指向了以XX為首地址的一片內(nèi)存區(qū)域;我們說一個指針指向了某塊內(nèi)存區(qū)域,就相當于說該指針的值是這塊內(nèi)存區(qū)域的首地址。指針所指向的內(nèi)存區(qū)和指針所指向的類型是兩個完全不同的概念。在例一中,指針所指向的類型已經(jīng)有了,但由于指針還未初始化,所以它所指向的內(nèi)存區(qū) 是不存在的,或者說是無意義的。以后,每遇到一個指針,都應該問問:這個指針的類型是什么?指針指向的類型是什么?該指針指向了哪里?

4。指針本身所占據(jù)的內(nèi)存區(qū)。

指針本身占了多大的內(nèi)存?你只要用函數(shù)sizeof(指針的類型)測一下就知道了。在32位平臺里,指針本身占據(jù)了4個字節(jié)的長度。指針本身占據(jù)的內(nèi)存這個概念在判斷一個指針表達式是否是左值時很有用。第二章。指針的算術運算

指針可以加上或減去一個整數(shù)。指針的這種運算的意義和通常的數(shù)值的加減運算的意義是不一樣的。例如: 例二: 1。char a[20];2。int *ptr=a;......3。ptr++;在上例中,指針ptr的類型是int*,它指向的類型是int,它被初始化為指向整形變量a。接下來的第3句中,指針ptr被加了1,編譯器是這樣處理的:它把指針 ptr的值加上了sizeof(int),在32位程序中,是被加上了4。由于地址是用字節(jié)做單位的,故ptr所指向的地址由原來的變量a的地址向高地址方向增加了4個字節(jié)。

由于char類型的長度是一個字節(jié),所以,原來ptr是指向數(shù)組a的第0號單元開始的四個字節(jié),此時指向了數(shù)組a中從第4號單元開始的四個字節(jié)。我們可以用一個指針和一個循環(huán)來遍歷一個數(shù)組,看例子: 例三: int array[20];int *ptr=array;...//此處略去為整型數(shù)組賦值的代碼。...for(i=0;i<20;i++){(*ptr)++;ptr++; } 這個例子將整型數(shù)組中各個單元的值加1。由于每次循環(huán)都將指針ptr加1,所以每次循環(huán)都能訪問數(shù)組的下一個單元。再看例子: 例四: 1。char a[20];2。int *ptr=a;......3。ptr+=5;在這個例子中,ptr被加上了5,編譯器是這樣處理的:將指針ptr的值加上5乘sizeof(int),在32位程序中就是加上了5乘4=20。由于地址的單位是字節(jié),故現(xiàn)在的ptr所指向的地址比起加5后的ptr所指向的地址來說,向高地址方向移動了20個字節(jié)。在這個例子中,沒加5前的ptr指向數(shù)組a的第0號單元開始的四個字節(jié),加5后,ptr已經(jīng)指向了數(shù)組a的合法范圍之外了。雖然這種情況在應用上會出問題,但在語法上卻是可以的。這也體現(xiàn)出了指針的靈活性。如果上例中,ptr是被減去5,那么處理過程大同小異,只不過ptr的值是被減去5乘sizeof(int),新的ptr指向的地址將比原來的ptr所指向的地址向低地址方向移動了20個字節(jié)。

總結一下,一個指針ptrold加上一個整數(shù)n后,結果是一個新的指針ptrnew,ptrnew的類型和ptrold的類型相同,ptrnew所指向的類型和ptrold所指向的類型也相同。ptrnew的值將比ptrold的值增加了n乘sizeof(ptrold所指向的類型)個字節(jié)。就是說,ptrnew所指向的內(nèi)存區(qū)將比ptrold所指向的內(nèi)存區(qū)向高地址方向移動了n乘sizeof(ptrold所指向的類型)個字節(jié)。一個指針ptrold減去一個整數(shù)n后,結果是一個新的指針ptrnew,ptrnew的類型和ptrold的類型相同,ptrnew所指向的類型和ptrold所指向的類型也相同。ptrnew的值將比ptrold的值減少了n乘sizeof(ptrold所指向的類型)個字節(jié),就是說,ptrnew所指向的內(nèi)存區(qū)將比ptrold所指向的內(nèi)存區(qū)向低地址方向移動了n乘sizeof(ptrold所指向的類型)個字節(jié)。

第三章。運算符&和* 這里&是取地址運算符,*是...書上叫做“間接運算符”。&a的運算結果是一個指針,指針的類型是a的類型加個*,指針所指向的類型是a的類型,指針所指向的地址嘛,那就是a的地址。*p的運算結果就五花八門了。總之*p的結果是p所指向的東西,這個東西有這些特點:它的類型是p指向的類型,它所占用的地址是p所指向的地址。例五: int a=12;int b;int *p;int **ptr;p=&a;//&a的結果是一個指針,類型是int*,指向的類型是int,指向的地址是a的地址。

*p=24;//*p的結果,在這里它的類型是int,它所占用的地址是p所指向的地址,顯然,*p就是變量a。

ptr=&p;//&p的結果是個指針,該指針的類型是p的類型加個*,在這里是int **。該指針所指向的類型是p的類型,這里是int*。該指針所指向的地址就是指針p自己的地址。

*ptr=&b;//*ptr是個指針,&b的結果也是個指針,且這兩個指針的類型和所指向的類型是一樣的,所以用&b來給*ptr賦值就是毫無問題的了。

**ptr=34;//*ptr的結果是ptr所指向的東西,在這里是一個指針,對這個指針再做一次*運算,結果就是一個int類型的變量。

第四章。指針表達式。

一個表達式的最后結果如果是一個指針,那么這個表達式就叫指針表達式。下面是一些指針表達式的例子: 例六: int a,b;int array[10];int *pa;pa=&a;//&a是一個指針表達式。

int**ptr=&pa;//&pa也是一個指針表達式。

*ptr=&b;//*ptr和&b都是指針表達式。

pa=array;pa++;//這也是指針表達式。例七: char*arr[20];char**parr=arr;//如果把arr看作指針的話,arr也是指針表達式 char*str;str=*parr;//*parr是指針表達式

str=*(parr+1);//*(parr+1)是指針表達式 str=*(parr+2);//*(parr+2)是指針表達式

由于指針表達式的結果是一個指針,所以指針表達式也具有指針所具有的四個要素:指針的類型,指針所指向的類型,指針指向的內(nèi)存區(qū),指針自身占據(jù)的內(nèi)存。

好了,當一個指針表達式的結果指針已經(jīng)明確地具有了指針自身占據(jù)的內(nèi)存的話,這個指針表達式就是一個左值,否則就不是一個左值。在例七中,&a不是一個左值,因為它還沒有占據(jù)明確的內(nèi)存。*ptr是一個左值,因為*ptr這個指針已經(jīng)占據(jù)了內(nèi)存,其實*ptr就是指針pa,既然pa已經(jīng)在內(nèi)存中有了自己的位置,那么*ptr當然也有了自己的位置。

第五章。數(shù)組和指針的關系

數(shù)組的數(shù)組名其實可以看作一個指針。看下例: 例八:

int array[10]={0,1,2,3,4,5,6,7,8,9},value;......value=array[0];//也可寫成:value=*array;value=array[3];//也可寫成:value=*(array+3);value=array[4];//也可寫成:value=*(array+4);

上例中,一般而言數(shù)組名array代表數(shù)組本身,類型是int [10],但如果把array看做指針的話,它指向數(shù)組的第0個單元,類型是int*,所指向的類型是數(shù)組單元的類型即int。因此*array等于0就一點也不奇怪了。同理,array+3是一個指向數(shù)組第3個單元的指針,所以*(array+3)等于3。其它依此類推。例九: char*str[3]={ “Hello,thisisasample!”, “Hi,goodmorning.”, “Helloworld” };chars[80];

strcpy(s,str[0]);//也可寫成strcpy(s,*str);strcpy(s,str[1]);//也可寫成strcpy(s,*(str+1));strcpy(s,str[2]);//也可寫成strcpy(s,*(str+2));上例中,str是一個三單元的數(shù)組,該數(shù)組的每個單元都是一個指針,這些指針各指向一個字符串。把指針數(shù)組名str當作一個指針的話,它指向數(shù)組的第0號單元,它的類型是char**,它指向的類型是char*。*str也是一個指針,它的類型是char*,它所指向的類型是char,它指向的地址是字符串“Hello,thisisasample!”的第一個字符的地址,即''H''的地址。str+1也是一個指針,它指向數(shù)組的第1號單元,它的類型是char**,它指向的類型是char*。*(str+1)也是一個指針,它的類型是char*,它所指向的類型是char,它指向“Hi,goodmorning.”的第一個字符''H'',等等。下面總結一下數(shù)組的數(shù)組名的問題。聲明了一個數(shù)組TYPEarray[n],則數(shù)組名稱array就有了兩重含義:第一,它代表整個數(shù)組,它的類型是TYPE[n];第二,它是一個指針,該指針的類型是TYPE*,該指針指向的類型是TYPE,也就是數(shù)組單元的類型,該指針指向的內(nèi)存區(qū)就是數(shù)組第0號單元,該指針自己占有單獨的內(nèi)存區(qū),注意它和數(shù)組第0號單元占據(jù)的內(nèi)存區(qū)是不同的。該指針的值是不能修改的,即類似array++的表達式是錯誤的。在不同的表達式中數(shù)組名array可以扮演不同的角色。在表達式sizeof(array)中,數(shù)組名array代表數(shù)組本身,故這時sizeof函數(shù) 測出的是整個數(shù)組的大小。在表達式*array中,array扮演的是指針,因此這個表達式的結果就是數(shù)組第0號單元的值。sizeof(*array)測出的是數(shù)組單元的大小。表達式array+n(其中n=0,1,2,....。)中,array扮演的是指針,故array+n的結果是一個指針,它的類型是TYPE*,它指向的類型是TYPE,它指向數(shù)組第n號單元。故sizeof(array+n)測出的是指針類型的大小。例十: int array[10];int(*ptr)[10];ptr=&array;上例中ptr是一個指針,它的類型是int(*)[10],他指向的類型是int[10],我們用整個數(shù)組的首地址來初始化它。在語句ptr=&array中,array代表數(shù)組本身。

本節(jié)中提到了函數(shù)sizeof(),那么我來問一問,sizeof(指針名稱)測出的究竟是指針自身類型的大小呢還是指針所指向的類型的大小?答案是前者。例如: int(*ptr)[10];則在32位程序中,有: sizeof(int(*)[10])==4 sizeof(int[10])==40 sizeof(ptr)==4 實際上,sizeof(對象)測出的都是對象自身的類型的大小,而不是別的什么類型的大小。

第六章。指針和結構類型的關系 可以聲明一個指向結構類型對象的指針。例十一: struct MyStruct { int a;int b;int c;}MyStruct ss={20,30,40};//聲明了結構對象ss,并把ss的三個成員初始化為20,30和40。MyStruct*ptr=&ss;//聲明了一個指向結構對象ss的指針。它的類型是MyStruct*, //它指向的類型是MyStruct。

int *pstr=(int*)&ss;//聲明了一個指向結構對象ss的指針。但是它的 //類型和它指向的類型和ptr是不同的。

請問怎樣通過指針ptr來訪問ss的三個成員變量? 答案: ptr->a;ptr->b;ptr->c;又請問怎樣通過指針pstr來訪問ss的三個成員變量? 答案:

*pstr;//訪問了ss的成員a。*(pstr+1);//訪問了ss的成員b。

*(pstr+2)//訪問了ss的成員c。

呵呵,雖然我在我的MSVC++6.0上調(diào)式過上述代碼,但是要知道,這樣使用pstr來訪問結構成員是不正規(guī)的,為了說明為什么不正規(guī),讓我們看看怎樣通過指針來訪問數(shù)組的各個單元: 例十二:

int array[3]={35,56,37};int*pa=array;通過指針pa訪問數(shù)組array的三個單元的方法是: *pa;//訪問了第0號單元 *(pa+1);//訪問了第1號單元

*(pa+2);//訪問了第2號單元

從格式上看倒是與通過指針訪問結構成員的不正規(guī)方法的格式一樣。所有的C編譯器在排列數(shù)組的單元時,總是把各個數(shù)組單元存放在連續(xù)的存儲區(qū)里,單元和單元之間沒有空隙。但在存放結構對象的各個成員時,在某種編譯環(huán)境下,可能會需要字對齊或雙字對齊或者是別的什么對齊,需要在相鄰兩個成員之間加若干個“填充字節(jié)”,這就導致各個成員之間可能會有若干個字節(jié)的空隙。所以,在例十二中,即使*pstr訪問到了結構對象ss的第一個成員變量a,也不能保證*(pstr+1)就一定能訪問到結構成員b。因為成員a和成員b之間可能會有若干填充字節(jié),說不定*(pstr+1)就正好訪問到了這些填充字節(jié)呢。這也證明了指針的靈活性。要是你的目的就是想看看各個結構成員之間到底有沒有填充字節(jié),嘿,這倒是個不錯的方法。通過指針訪問結構成員的正確方法應該是象例十二中使用指針ptr的方法。

第七章。指針和函數(shù)的關系

可以把一個指針聲明成為一個指向函數(shù)的指針。int fun1(char*,int);int(*pfun1)(char*,int);pfun1=fun1;........inta=(*pfun1)(“abcdefg”,7);//通過函數(shù)指針調(diào)用函數(shù)。

可以把指針作為函數(shù)的形參。在函數(shù)調(diào)用語句中,可以用指針表達式來作為實參。例十三: int fun(char*);int a;char str[]=“abcdefghijklmn”;a=fun(str);......int fun(char*s){ int num=0;while(*s!= ''

主站蜘蛛池模板: 国产自偷在线拍精品热乐播av| 加勒比色老久久爱综合网| 无码熟妇αⅴ人妻又粗又大| 性色av闺蜜一区二区三区| 成人丝袜激情一区二区| 99热精品毛片全部国产无缓冲| 亚洲精品成人av观看| 综合图区亚洲另类偷窥| 久久久久噜噜噜亚洲熟女综合| 正在播放熟妇群老熟妇456| 高清同性男毛片| 无码人妻精品一区二区蜜桃网站| 在线精品视频一区二区| 精品成在人线av无码免费看| 亚洲国产精品无码久久久秋霞1| 国语自产精品视频在线30| 成人精品av一区二区三区网站| 亚洲av激情无码专区在线播放| 国产精品对白交换视频| 日韩亚洲中字无码一区二区三区| 亚洲欧美国产精品无码中文字| www插插插无码视频网站| 亚洲精品久久久www小说| 国产国拍亚洲精品mv在线观看| 男女做爰高清无遮挡免费视频| 欧美亚洲国产一区二区三区| 日韩性爱视频| 99精品欧美一区二区三区| 国产欧美日本亚洲精品一5区| 国产白袜脚足j棉袜在线观看| 99久久人人爽亚洲精品美女| 天天做天天爱天天爽天天综合| 日日摸夜夜添夜夜添无码免费视频| 在线日本国产成人免费不卡| 亚洲精品无码不卡在线播放he| 国产精品综合av一区二区| 精品无码日韩国产不卡av| 日本真人边吃奶边做爽免费视频| 日韩亚洲国产综合高清| 中文字幕亚洲欧美日韩2019| 久久人人爽人人爽人人片av|