當前位置:首頁 » 編程語言 » c語言指針知識點
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

c語言指針知識點

發布時間: 2022-12-22 12:30:25

1. 為什麼很多人覺得c語言只要學會了指針基本上差不多掌握這門語言

從事嵌入式開發十幾年,只要使用的編程語言有三種,C/C++ Java三種,其中C語言使用的時間最長,這門編程語言的最大特別是語法細節簡介,但是靈活性非常強,從大的方面看要真正掌握一種編程語言,需要真正的項目實戰,只是停留在理論層面上很難認清編程語言背後的本質,記得剛學習C語言階段,基本上一個多月就把基礎語法學習完了,並且做了大量的實習題目,覺得這門編程語言就這么回事了。

於是從學校的圖書館裡面借了一本將近1000頁的linux內核講解書籍,開始先從戰略上藐視對手,在戰術上重視在開始幾十頁進展的還是比較順利,始終覺得掌握好了基礎的語法,後面的就是變通和靈活運用的問題了,還能變出什麼幺蛾子結果,看到後面簡直就是在閱讀天書了,才知道了自己認識的淺薄,只是掌握點語法皮毛就想著挑大樑這種想法在編程行業顯得非常的幼稚,編程行業除了理論之外實戰經驗顯得非常重要。

回到題目中的C語言的核心知識點指針,C語言關鍵語法點指針,數組,結構體,回調,遞歸,函數等等,剩下就是這些個概念在項目實戰中的應用了,指針對於初學者來講就是一種雙刃劍,如果真的掌握理解了,能在編程中提升非常大的效率,如果沒有掌握對於很多初學者來講就是一種折磨,很多人覺得學不好C語言版本的數據結構,其實很重要的一個障礙就是指針,如果對於指針了解清楚,再去切入數據結構的學習就會顯得輕松許多,指針作為C語言裡面最重要的語法一點不為過,但是認為掌握了指針C語言就會顯得非常膚淺。

任何一種編程語言的背後都是大量的編程模式以及編程的套路,這些只有在真正的項目實戰中才能掌握,而且對於一種編程語言越是做的時間長越是覺得自己的膚淺,更加不敢稱之為精通,倒是現在很多初生牛犢在簡歷上寫上精通幾種編程語言,越是乾的時間長越是忌諱提到精通兩個字眼,所以講只是掌握了指針就說掌握一門編程語言的一半顯得認識不足,真正掌握編程語言還是靠項目實戰,不是所謂幾個重點語法這么簡單的事情。

學習一種編程語言需要掌握幾個重點要素,首先掌握理論基礎,世要真正的明白,雖然編程語言是一種實踐性的語言,但實踐的前提是掌握理論基礎,很多人不懂C語言的指針就是因為沒有徹底明白指針的含義,只想著快點追趕進度,結果欲速則不達,越是重要的概念越是要徹底掌握明白;第二點就是實戰,在掌握理論基礎上就是通過項目實戰獲取經驗,紙上談兵永遠也不做不了真正的項目,想盡一切辦法去做項目實戰,沒有別的途徑,直面問題的本質,希望能幫到你。

很高興能回答你的問題

C語言作為編程老祖,很多軟體工具腳本都是用C語言或C++來編寫的。那麼C語言到底學成什麼樣才算學的比較好?

我上大學一年級的時候,就開始接觸C語言了,C語言自認為學的還可以。像數據、變數、循環、判斷等都是手到擒來。但學到第8章,也就是學到了指針那一塊,就感覺有一點懵了,老師也說指針是比較費腦力的,死記硬背是不可取的,需要理解它的含義。

在學習指針之前,基本都沒了解面向對象是什麼意思。但學到了指針就懂得面向對象與面向過程的差異。(簡單來說,前者就是以對象為基礎,設定其屬性啊,行為等。後者就是以完成它的過程為主,比如說:計算兩個數相加。前者可以設計為小貓計算兩個數,也可以是小貓2......,而後者就是計算,而且可以具體到是哪兩個數相加。)面向對象對於現在的編程語言還是很重要的。

個人覺得,指針與面向對象密切相關,導致在C語言中指針就變得尤其重要,像我後面學習的Python、java就沒有指針一說,但出現了很多類。相對C語言來說,多出了很多很多類。可能是指針被封裝起來了吧。

更多精彩,敬請期待!

指針遠遠不是C語言的全部,

只是在C語言學習道路上相對而言比較難理解的一塊。

畢竟從一個高級語言的角度去理解地址,比較抽象。

作為一個高級語言,數據類型,流程式控制制,函數這些才是高級語言的重點。

說差不多掌握這門語言,應該就是指的指針的難度,和學習的耗時。

也對,也不對,學會指針只是入門了。位運算與文件學會才能寫應用。

只要學過嵌入式開發對指針必定是秒懂,無非就是內存定址。脫離了硬體去學C只能學點皮毛。充其量也只能說會點語法而已。線程進程信號量系統調用各種通訊協議這些才是精華所在。

c語言是結構性(相對面向對象編程語言)高級編程語言。單純語言本身來講,語法結構大致類同。c語言的一大特點是對內存操作的靈活性,如果理解了對內存操作和管理的知識點,基本就掌握了這門語言。而指針便是c語言對內存操作的金鑰匙。要想掌握c語言,也必須要精通指針相關知識點。

如果不算數據結構、操作系統和演算法這些東西。純粹從語言角度來看,掌握指針技巧,確實可以認為基本掌握語言了。要想更加精進的話,可以考慮學習各個硬體平台了。

比如SIMD在各個CPU平台的實現等。做一些針對性的硬體優化是可以考慮的。多媒體庫就做了大量的硬體針對性優化。這個內容也算是核心技術的一部分了。核心技術的另一部分可以認為是演算法和操作系統知識的應用。

首先說明的是指針是C語言的一個難點,但是不是全部。就好比不會指針,很多編程技巧無法掌握,同樣掌握指針也不見得你能做什麼。很多編程技巧需要在實際項目中去體會和學習。等覺得自己像編譯器一樣思考,自己寫的每句代碼,都很清楚編譯器背後是怎麼處理的時候再說自己熟練掌握C語言了。

最後總結來說,掌握指針只是C語言"真正"入門的一個表現。

語言本身掌握不算難,重點是演算法,數據結構,編程思想...

我一般自己設計編譯器 c指針按我自己的想法來寫 怎麼的

2. c語言指針面試常見問題

c語言指針面試常見問題

指針的使用,一直是c語言面試題中必考的部分,因為指針本身使用的復雜性與普適性,所以考點非常多,而且也可以與其他知識相互結合,因此我們將會使用五篇專題的篇幅來介紹指針。

分析下面的程序,指出程序中的錯誤:

本題解析

沒有正確為str分配內存空間,將會發生異常。問題出在將一個字元串復制進一個字元變數指針所指地址。雖然編譯的時候沒有報錯,但是在運行過程中,因為越界訪問了未被分配的內存,而導致段錯誤。

相關知識點

在處理與指針相關的問題時,首先需要搞明白的就是內存,因為指針操作的就是內存。

第一個,就是內存的分區。這也是經常會被考察的一個考點。

寫出內存分為幾大區域

對於這個問題,有幾種不同的說法,有的說內存分為五大分區,有的說分為四大分區,我們先來看五大分區的說法:

認為內存分為五大分區的人,通常會這樣劃分:

1、BSS段( bss segment )

通常是指用來存放程序中未初始化的'全局變數和靜態變數 (這里注意一個問題:一般的書上都會說全局變數和靜態變數是會自動初始化的,那麼哪來的未初始化的變數呢?變數的初始化可以分為顯示初始化和隱式初始化,全局變數和靜態變數如果程序員自己不初始化的話的確也會被初始化,那就是不管什麼類型都初始化為0,這種沒有顯示初始化的就 是我們這里所說的未初始化。既然都是0那麼就沒必要把每個0都存儲起來,從而節省磁碟空間,這是BSS的主要作用)的一塊內存區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬於靜態內存分配。 BSS節不包含任何數據,只是簡單的維護開始和結束的地址,即總大小。以便內存區能在運行時分配並被有效地清零。BSS節在應用程序的二進制映象文件中並不存在,即不佔用 磁碟空間 而只在運行的時候佔用內存空間 ,所以如果全局變數和靜態變數未初始化那麼其可執行文件要小很多。

2、數據段(data segment)

通常是指用來存放程序中已經初始化的全局變數和靜態變數的一塊內存區域。數據段屬於靜態內存分配,可以分為只讀數據段和讀寫數據段。字元串常量等,但一般都是放在只讀數據段中。

3、代碼段(code segment/text segment)

通常是指用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行前就已經確定,並且內存區域通常屬於只讀, 某些架構也允許代碼段為可寫,即允許修改程序。在代碼段中,也有可能包含一些只讀的常數變數,例如字元串常量等,但一般都是放在只讀數據段中 。

4、堆(heap)

堆是用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或 縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張); 當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)

5、棧 (stack)

棧又稱堆棧, 是用戶存放程序臨時創建的局部變數,也就是說我們函數括弧「{}」 中定義的變數(但不包括static聲明的變數,static意味著在數據段中存放變 量)。除此以外, 在函數被調用時,其參數也會被壓入發起調用的進程棧中,並且待到調用結束後,函數的返回值 也會被存放回棧中。由於棧的先進先出特點,所以 棧特別方便用來保存/恢復調用現場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數據的內存區。

而四大分區的說法,則這么認為:

1、堆區:

由程序員手動申請,手動釋放,若不手動釋放,程序結束後由系統回收,生命周期是整個程序運行期間。使用malloc或者new進行堆的申請,堆的總大小為機器的虛擬內存的大小。

說明:new操作符本質上是使用了malloc進行內存的申請,new和malloc的區別如下:

(1)malloc是C語言中的函數,而new是C++中的操作符。

(2)malloc申請之後返回的類型是void*,而new返回的指針帶有類型。

(3)malloc只負責內存的分配而不會調用類的構造函數,而new不僅會分配內存,而且會自動調用類的構造函數。

2、棧區:

由系統進行內存的管理。主要存放函數的參數以及局部變數。在函數完成執行,系統自行釋放棧區內存,不需要用戶管理。整個程序的棧區的大小可以在編譯器中由用戶自行設定,VS中默認的棧區大小為1M,可通過VS手動更改棧的大小。64bits的Linux默認棧大小為10MB,可通過ulimit -s臨時修改。

3、靜態存儲區:

靜態存儲區內的變數在程序編譯階段已經分配好內存空間並初始化。這塊內存在程序的整個運行期間都存在,它主要存放靜態變數、全局變數和常量。

注意:

(1)這里不區分初始化和未初始化的數據區,是因為靜態存儲區內的變數若不顯示初始化,則編譯器會自動以默認的方式進行初始化,即靜態存儲區內不存在未初始化的變數。

(2)靜態存儲區內的常量分為常變數和字元串常量,一經初始化,不可修改。靜態存儲內的常變數是全局變數,與局部常變數不同,區別在於局部常變數存放於棧,實際可間接通過指針或者引用進行修改,而全局常變數存放於靜態常量區則不可以間接修改。

(3)字元串常量存儲在靜態存儲區的常量區,字元串常量的名稱即為它本身,屬於常變數。

(4)數據區的具體劃分,有利於我們對於變數類型的理解。不同類型的變數存放的區域不同。後面將以實例代碼說明這四種數據區中具體對應的變數。

4、代碼區:

存放程序體的二進制代碼。比如我們寫的函數,都是在代碼區的。

通過上面的不同說法,我們也可以看出,這兩種說法本身沒有優劣之分,具體的內存劃分也跟編譯器有很大的關系,因此這兩種說法都是可以接受的,搞明白內存的分區之後,指針的使用才能夠更加的靈活。

;

3. C語言包括哪些知識點

數據類型,運算符與表達式;程序結構:順序,選擇,循環; 數組,函數,預處理命令,指針,結構體與共用體,文件,位運算;
當然,C程序的靈魂是演算法。

4. 有關C語言指針的問題,超難,高手進!!!

整個函數的作用是-->在以listelement * listpointer為單向鏈表頭的單向鏈表中的最尾段動態申請一個listelement結構的空間來存放要求加進單向鏈表的int data數據.並返回該鏈表的頭指針....

以下是對程序代碼的詳細解釋...

listelement * AddItem (listelement * listpointer, int data) {
//listpointer指向需要執行加入數據的單向鏈表的指針.這個指針可以指向任一條數據結構為listelement的單向鏈表
//data指的是要加入單向鏈表的具體數據

listelement * lp = listpointer; //使lp指向即將進行鏈表編歷的頭指針,這句為關鍵語句!

if (listpointer != NULL) { //如果鏈單不止一個有效項...則...

while (listpointer -> link != NULL)
listpointer = (listelement *) listpointer -> link; //這兩名加起來為一個循環體! 其作用是編歷整個鏈表的項.並保證listpointer指向鏈表中的最後一項!邏輯規定鏈表中的最後一項的listpointer -> link為NULL 其中listpointer = (listelement *) listpointer -> link中的(listelement *)為強制數據類型轉換!目的是100%確保link為指向listelement結構的指針...這句話其實在正常的邏輯下是多餘的.除非link除了指向本鏈表的下一個數據項外,還有別的作用! 但這樣的可能性很少....

listpointer -> link = (struct listelement *) malloc (sizeof (listelement)); //動態申請一個listelement結構空間,並把申請到的首地址作為listpointer -> link! 由於前面的循環體的作用,使得listpointer -> link確保為鏈單中的最後一項...

listpointer = listpointer -> link; //使listpointer指向最後一項的實體,以便加入指定data數據項....看,這句listpointer = (listelement *) listpointer -> link是多麼的相似!?(其執行結果肯定是一樣的) 從這里可以看出,在前面循環體內的(listelement *)肯定是多餘的!!!
listpointer -> link = NULL; //使listpointer在邏輯上成為本鏈表的最尾部!

listpointer -> dataitem = data; //加入數據
return lp; //返回本鏈表的頭指針! 這和函數的第一句是對應的,是關鍵語句,絕不能少的!
}
else { //如果鏈表為空,也就是一個數據項都沒有的話,則動態申請一個,並把data數據加到裡面保存,然後使剛動態生成的listpointer為鏈表頭指針! (以下的語句作用是就如此,我不多說了)

listpointer = (struct listelement *) malloc (sizeof (listelement));
listpointer -> link = NULL;
listpointer -> dataitem = data;
return listpointer;
}
}

PS:在高級語言里,指針的強制類型轉換是經常用到的技巧!但由於各編譯器的不同,會造成很多意想不到的邏輯錯誤!!!(很多時候,你以為確實是按自己的意思轉換成指定的類型了,但實際上卻完全不是這么一回事! 並這個錯誤有時是很難很難檢測到底是為什麼的!!!) 指針,用好了天下無敵,用不好就是一滴老鼠屎搞臭一鍋湯!!! 這樣情況的應用,用匯編是最不容易出錯的!

PS:舉個在G++編譯器里一個容易誤解的指針例子...兩個不同的指針定義-->char *lp=new char[255]; 和 char lp[255];
里具體語句的lp[1]的含義到底有什麼樣的區別!? 這個例子,相信很多人都會覺得是一樣沒區別的(這是在C++標准里說明的)...但實際上,如果是在G++編譯器里的話.定義為char lp[255];中的lp[1]的意義就是以lp為頭指針的下一個單元!在這里,是我們常規並正確的理解! 但是,如果寶義成char *lp=new char[255];的話,則在G++編譯器里lp[1]無解(結果是隨機亂指一通)!!!雖然編譯時不會出錯,但結果肯定是錯誤的! 解決的方法超級郁悶.只能通過lp++來一步步定址!(而不能通過lp[n]的方式直接定址,當然如果還有效率高的方法,但這在邏輯上很容易讓人混亂,那就是先把lp[0]轉成DWORD類型再加上n之後再強制轉成相應的指針類型!)

5. c語言指針程序題,程序如下,答案是3,6。我想知道為什麼答案是3,6而不是6,3希望您能幫我詳細解答一下。

呵呵,你被主函數中的a,b和子函數中的a,b所混淆了!
(1)主函數中的a,b是變數名,a=3,b=6,內容為3和6 。
(2)子函數中的a,b是指針變數,是指向整型變數的指針變數【(int * a,int * b)】。k也是指針變數,調用子函數fun時【fun(x,y)】,是將a,b的地址傳過來了,不是a,b的值!在子函數內部,
k=a;a=b;b=k;交換的是就是的地址(注意:這里的a,b實際上是x,y,也就是主函數中的&a,&b),也就是將主函數中的變數地址交換了而已,就是將變數換個地方而已,變數名和變數的值都沒有變!
指針變數是C語言中比較難的一個知識點,尤其是指向指針的指針、指向多維數組的指針。希望你多看書,多練習,認真領會。

6. c語言指針,下面這題看不懂,求解😭

  1. while (*y++)

    因為++運算符優先順序比*高,所以先對指針y加1,再取出指針y指向的 字元

    如果取出的字元不為0() 就循環

    因為字元串數組 a[]={hello} 是依字元''結尾,字元''的ASCII 碼值 是0

    這樣當指針y 指向''時 就結束循環。

  2. return (y-x-1)

    y x 都是指針,是內存地址,y-x-1 就兩個指針相減再減1 ,返回運算結果。

  3. 從實際執行結果看 返回的是5

    這樣y-x=6

    其實實際循環了5次,但是y 和 x 兩個指針卻相差6

    是因為++的優先順序比*高導致的。

  4. 希望我的回答對你有點幫助,很高興和你一起討論和學習C語言。

    C語言的指針是比較難理解的知識點,需要多練習才能掌握。

7. C語言怎麼讓指針指向某個變數

首先要知道兩個最基礎的知識點:
1、&a指向的是a的地址。
2、指針指向的是地址,和整型變數的值並不對等,也就是int *與int不對等,是不能從int轉換為int *的。
知道以上兩個最基礎的知識點,你的問題就很簡單了 。
第一個:
int *p;

p=&a;
是正確的。定義指針變數p,然後才將p指向變數a的地址。
第二個:
int *p;
p=int* (&a);
p是指針,指向的是地址,而不是int型值,因此是錯誤的。
第三個:
int *p=a;
不能從int轉換為int *,因此是錯誤的。
只有第一個是正確的,後面兩個都是錯誤的。

8. 為什麼c語言指針那麼難

指針確實難於理解。指針具有兩個身份:

第一,指針本身是一個變數。只要是是變數,它就佔用內存地址。當然如果沒有分配內存地址,不在其內。

第二,指針包含一定的一個內容。指針所特殊的就是,他的內容保存的是其他變數的地址。

以上兩點可以通過書中的示例7-7有比較好的體現。

例如,定義指針變數intp1。 intp1=&a 就表示 intp1保存的信息為a的地址。
而*intp1表示是intp1所保存地址的內存單元所保存的值,實際就是a的值。

所以,你給出的 *intp1=&a; 是一種不太合適寫法。我們可以這樣假設,再給一個變數b。令*intp1=b=&a,則
b=&a,說明b保存的a的地址,這樣b就是一個指針。那*intp1=b,則說明 intp1所保存的地址指向的內存單元為b。所以,intp1可以看成a的指針的指針。

上面這個例子比較繞,慢慢想想,就理解了。

9. 計算機二級c語言知識點

2017計算機二級c語言知識點精選

計算機二級C語言考試內容是什麼?為幫助大家更好備考3月計算機考試,我為大家分享計算機C語言二級考試知識點如下:

第一章 數據結構與演算法

1.1 演算法

1.演算法的基本概念

(1) 概念:演算法是指一系列解決問題的清晰指令。

(2) 4個基本特徵:可行性、確定性、有窮性、擁有足夠的情報。

(3) 兩種基本要素:對數據對象的運算和操作、演算法的控制結構(運算和操作時問的順序)。

(4) 設計的基本方法:列舉法、歸納法、遞推法、遞歸法、減半遞推技術和回溯法。

2.演算法的復雜度

(1) 演算法的時間復雜度:執行演算法所需要的計算工作量。

(2) 演算法的空間復雜度:執行演算法所需的內存空間。

1.2 數據結構的基本概念

數據結構指相互有關聯的數據元素的集合,即數據的組織形式。其中邏輯結構反映數據元素之間邏輯關系;存儲結構為數據的邏輯結構在計算機存儲空間中的存放形式,有順序存儲、鏈式存儲、索引存儲和散列存儲4種方式。

數據結構按各元素之間前後件關系的復雜度可劃分為:

(1) 線性結構:有且只有一個根節點,且每個節點最多有一個直接前驅和一個直接後繼的非空數據結構。

(2) 非線性結構:不滿足線性結構的數據結構。

1.3 線性表及其順序存儲結構

1.線性表的基本概念

線性結構又稱線性表,線性表是最簡單也是最常用的一種數據結構。

2.線性表的順序存儲結構

元素所佔的存儲空間必須連續。

元素在存儲空間的位置是按邏輯順序存放的。

3.線性表的插入運算

在第i個元素之前插入一個新元素的步驟如下:

步驟一:把原來第n個節點至第i個節點依次往後移一個元素位置。

步驟二:把新節點放在第i個位置上。

步驟三:修正線性表的節點個數。

在最壞情況下,即插入元素在第一個位置,線性表中所有元素均需要移動。

4.線性表的刪除運算

刪除第i個位置的元素的步驟如下:

步驟一:把第i個元素之後不包括第i個元素的n-i個元素依次前移一個位置;

步驟二:修正線性表的結點個數。

1.4 棧和隊列

1.棧及其基本運算

(1) 基本概念:棧是一種特殊的線性表,其插入運算與刪除運算都只在線性表的一端進行,也被稱為「先進後出」表或「後進先出」表。

棧頂:允許插入與刪除的一端。

棧底:棧頂的另一端。

空棧:棧中沒有元素的棧。

(2) 特點。

棧頂元素是最後插入和最早被刪除的元素。

棧底元素是最早插入和最後被刪除的元素。

棧有記憶作用。

在順序存儲結構下,棧的插入和刪除運算不需移動表中其他數據元素。

棧頂指針top動態反映了棧中元素的變化情況

(3) 順序存儲和運算:入棧運算、退棧運算和讀棧頂運算。

2.隊列及其基本運算

(1) 基本概念:隊列是指允許在一端進行插入,在另一端進行刪除的線性表,又稱「先進先出」的線性表。

隊尾:允許插入的一端,用尾指針指向隊尾元素。

排頭:允許刪除的一端,用頭指針指向頭元素的前一位置。

(2) 循環隊列及其運算。

所謂循環隊列,就是將隊列存儲空間的最後一個位置繞到第一個位置,形成邏輯上的環狀空間。

入隊運算是指在循環隊列的隊尾加入一個新元素。

當循環隊列非空(s=1)且隊尾指針等於隊頭指針時,說明循環隊列已滿,不能進行人隊運算,這種情況稱為「上溢」。

退隊運算是指在循環隊列的隊頭位置退出一個元素並賦給指定的變數。首先將隊頭指針進一,然後將排頭指針指向的元素賦給指定的變數。當循環隊列為空(s=0)時,不能進行退隊運算,這種情況稱為「下溢」。

1.5 線性鏈表

在定義的鏈表中,若只含有一個指針域來存放下一個元素地址,稱這樣的鏈表為單鏈表或線性鏈表。

在鏈式存儲方式中,要求每個結點由兩部分組成:一部分用於存放數據元素值,稱為數據域;另一部分用於存放指針,稱為指針域。其中指針用於指向該結點的前一個或後一個結點(即前件或後件)。

1.6 樹和二叉樹

1.樹的基本概念

樹是簡單的非線性結構,樹中有且僅有一個沒有前驅的節點稱為「根」,其餘節點分成m個互不相交的有限集合T1,T2,…,T}mm,每個集合又是一棵樹,稱T1,T2,…,T}mm為根結點的子樹。

父節點:每一個節點只有一個前件,無前件的節點只有一個,稱為樹的根結點(簡稱樹的根)。

子節點:每~個節點可以後多個後件,無後件的節點稱為葉子節點。

樹的度:所有節點最大的度。

樹的深度:樹的最大層次。

2.二叉樹的定義及其基本性質

(1) 二叉樹的定義:二叉樹是一種非線性結構,是有限的節點集合,該集合為空(空二叉樹)或由一個根節點及兩棵互不相交的左右二叉子樹組成。可分為滿二叉樹和完全二叉樹,其中滿二叉樹一定是完全二叉樹,但完全二叉樹不一定是滿二叉樹。二叉樹具有如下兩個特點:

二叉樹可為空,空的二叉樹無節點,非空二叉樹有且只有一個根結點;

每個節點最多可有兩棵子樹,稱為左子樹和右子樹。

(2) 二叉樹的基本性質。

性質1:在二叉樹的第k層上至多有2k-1個結點(k≥1)。

性質2:深度為m的二叉樹至多有2m-1個結點。

性質3:對任何一棵二叉樹,度為0的結點(即葉子結點)總是比度為2的結點多一個。

性質4:具有n個結點的完全二叉樹的深度至少為[log2n]+1,其中[log2n]表示log2n的整數部分。

3.滿二叉樹與完全二叉樹

(1) 滿二叉樹:滿二叉樹是指這樣的一種二叉樹:除最後一層外,每一層上的所有結點都有兩個子結點。滿二叉樹在其第i層上有2i-1個結點。

從上面滿二叉樹定義可知,二叉樹的每一層上的結點數必須都達到最大,否則就不是滿二叉樹。深度為m的滿二叉樹有2m-1個結點。

(2) 完全二叉樹:完全二叉樹是指這樣的二叉樹:除最後一層外,每一層上的結點數均達到最大值;在最後一層上只缺少右邊的若干結點。

如果—棵具有n個結點的深度為k的二叉樹,它的每—個結點都與深度為k的滿二叉樹中編號為1~n的結點——對應。

3.二叉樹的存儲結構

二叉樹通常採用鏈式存儲結構,存儲節點由數據域和指針域(左指針域和右指針域)組成。二叉樹的鏈式存儲結構也稱二叉鏈表,對滿二叉樹和完全二叉樹可按層次進行順序存儲。

4.二叉樹的遍歷

二叉樹的遍歷是指不重復地訪問二叉樹中所有節點,主要指非空二叉樹,對於空二叉樹則結束返回。二叉樹的遍歷包括前序遍歷、中序遍歷和後序遍歷。

(1) 前序遍歷。

前序遍歷是指在訪問根結點、遍歷左子樹與遍歷右子樹這三者中,首先訪問根結點,然後遍歷左子樹,最後遍歷右子樹;並且,在遍歷左右子樹時,仍然先訪問根結點,然後遍歷左子樹,最後遍歷右子樹。前序遍歷描述為:若二叉樹為空,則執行空操作;否則①訪問根結點;②前序遍歷左子樹;③前序遍歷右子樹。

(2) 中序遍歷。

中序遍歷是指在訪問根結點、遍歷左子樹與遍歷右子樹這三者中,首先遍歷左子樹,然後訪問根結點,最後遍歷右子樹;並且,在遍歷左、右子樹時,仍然先遍歷左子樹,然後訪問根結點,最後遍歷右子樹。中序遍歷描述為:若二叉樹為空,則執行空操作;否則①中序遍歷左子樹;②訪問根結點;③中序遍歷右子樹。

(3) 後序遍歷。

後序遍歷是指在訪問根結點、遍歷左子樹與遍歷右子樹這三者中,首先遍歷左子樹,然後遍歷右子樹,最後訪問根結點,並且,在遍歷左、右子樹時,仍然先遍歷左子樹,然後遍歷右子樹,最後訪問根結點。後序遍歷描述為:若二叉樹為空,則執行空操作;否則①後序遍歷左子樹;②後序遍歷右子樹;③訪問根結點。

1.7 查找技術

(1) 順序查找:在線性表中查找指定的元素。

(2) 最壞情況下,最後一個元素才是要找的元素,則需要與線性表中所有元素比較,比較次數為n。

(3) 二分查找:二分查找也稱折半查找,它是一種高效率的查找方法。但二分查找有條件限制,它要求表必須用順序存儲結構,且表中元素必須按關鍵字有序(升序或降序均可)排列。對長度為n的有序線性表,在最壞情況下,二分查找法只需比較log2n次。

1.8 排序技術

(1) 交換類排序法。

冒泡排序:通過對待排序序列從後向前或從前向後,依次比較相鄰元素的排序碼,若發現逆序則交換,使較大的元素逐漸從前部移向後部或較小的元素逐漸從後部移向前部,直到所有元素有序為止。在最壞情況下,對長度為n的線性表排序,冒泡排序需要比較的次數為n(n-1)/2。

快速排序:是迄今為止所有內排序演算法中速度最快的一種。它的基本思想是:任取待排序序列中的某個元素作為基準(一般取第一個元素),通過一趟排序,將待排元素分為左右兩個子序列,左子序列元索的排序碼均小於或等於基準元素的排序碼,右子序列的排序碼則大於基準元素的排序碼,然後分別對兩個子序列繼續進行排序,直至整個序列有序。最壞情況下,即每次劃分,只得到一個序列,時間效率為O(n2)。

(2) 插人類排序法。

簡單插入排序法:把n個待排序的元素看成為一個有序表和一個無序表,開始時有序表中只包含一個元素,無序表中包含有n-1個元素,排序過程中每次從無序表中取出第一個元素,把它的排序碼依次與有序表元素的排序碼進行比較,將它插入到有序表中的適當位置,使之成為新的有序表。在最壞情況下,即初始排序序列是逆序的情況下,比較次數為n(n-1)/2,移動次數為n(n-1)/2。

希爾排序法:先將整個待排元素序列分割成若干個子序列(由相隔某個「增量」的元素組成的)分別進行直接插入排序。待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。

(3) 選擇類排序法。

簡單選擇排序法:掃描整個線性表。從中選出最小的元素。將它交換到表的最前面;然後對剩下的子表採用同樣的方法,直到子表空為止。最壞情況下需要比較n(n-1)/2次。

堆排序的方法:首先將一個無序序列建成堆;然後將堆頂元素(序列中的最大項)與堆中最後一個元素交換(最大項應該在序列的最後)。不考慮已經換到最後的那個元素,只考慮前n-1個元素構成的子序列,將該子序列調整為堆。反復做步驟②,直到剩下的子序列空為止。在最壞情況下,堆排序法需要比較的次數為0(nlog2n)

第二章 程序設計基礎

2.1 程序設計方法與風格

(1)設計方法:指設計、編制、調試程序的方法和過程,主要有結構化程序設計方法、軟體工程方法和面向對象方法。

(2)設計風格:良好的'設計風格要注重源程序文檔化、數據說明方法、語句的結構和輸入輸出。

2.2 結構化程序設計

1.結構化程序設計的原則

結構化程序設計強調程序設計風格和程序結構的規范化,提倡清晰的結構。。

(1)自頂向下:即先考慮總體,後考慮細節;先考慮全局目標,後考慮局部目標。

(2)逐步求精:對復雜問題,應設計一些子目標做過渡,逐步細化。

(3)模塊化:把程序要解決的總目標分解為分目標,再進一步分解為具體的小目標,把每個小目標稱為一個模塊;

(4)限制使用GOT0語句。

2.結構化程序的基本結構與特點

(1)順序結構:自始至終嚴格按照程序中語句的先後順序逐條執行,是最基本、最普遍的結構形式。

(2)選擇結構:又稱為分支結構,包括簡單選擇和多分支選擇結構。

(3)重復結構:又稱為循環結構,根據給定的條件,判斷是否需要重復執行某一相同的或類似的程序段。

結構化程序設計中,應注意事項:

(1)使用程序設計語言中的順序、選擇、循環等有限的控制結構表示程序的控制邏輯。

(2)選用的控制結構只准許有一個人口和一個出口。

(3)程序語言組成容易識別的塊,每塊只有一個入口和一個出口。

(4)復雜結構應該用嵌套的基本控制結構進行組合嵌套來實現。

(5)語言中所沒有的控制結構,應該採用前後一致的方法來模擬。

(6)盡量避免GOT0語句的使用。

2.3 面向對象的程序設計

面向對象方法的本質是主張從客觀世界固有的事物出發來構造系統,強調建立的系統能映射問題域。

對象:用來表示客觀世界中任何實體,可以是任何有明確邊界和意義的東西。

類:具有共同屬性、共同方法的對象的集合。

實例:一個具體對象就是其對應分類的一個實例。

消息:實例間傳遞的信息,它統一了數據流和控制流。

繼承:使用已有的類定義作為基礎建立新類的定義技術。

多態性:指對象根據所接受的信息而作出動作,同樣的信息被不同的對象接收時有不同行動的現象。面向對象程序設計的優點:與人類習慣的思維方法一致、穩定性好、可重用性好、易於開發大型軟體產品、可維護性好。

第三章 軟體工程基礎

3.1 軟體工程基本概念

1.軟體的定義與特點

(1)定義:軟體是指與計算機系統的操作有關的計算機程序、規程、規則,以及可能有的文件、文檔和數據。

(2)特點。

是邏輯實體,有抽象性。

生產沒有明顯的製作過程。

運行使用期間不存在磨損、老化問題。

開發、運行對計算機系統有依賴性,受計算機系統的限制,導致了軟體移植問題。

復雜性較高,成本昂貴。

開發涉及諸多社會因素。

2.軟體的分類

軟體可分應用軟體、系統軟體和支撐軟體3類。

(1)應用軟體是特定應用領域內專用的軟體。

(2)系統軟體居於計算機系統中最靠近硬體的一層,是計算機管理自身資源,提高計算機使用效率並為計算機用戶提供各種服務的軟體。

(3)支撐軟體介於系統軟體和應用軟體之間,是支援其它軟體的開發與維護的軟體。

3.軟體危機與軟體工程

軟體危機指在計算機軟體的開發和維護中遇到的一系列嚴重問題。軟體工程是應用於計算機軟體的定義、開發和維護的一整套方法、工具、文檔、實踐標准和工序,包括軟體開發技術和軟體工程管理。

4.軟體生命周期

軟體產品從提出、實現、使用維護到停止使用的過程稱為軟體生命周期。

在國家標准中,軟體生命周期劃分為8個階段①軟體定義期:包括問題定義、可行性研究和需求分析3個階段。②軟體開發期:包括概要設計、詳細設計、實現和測試4個階段。③運行維護期:即運行維護階段。

5.軟體工程的原則

軟體工程的原則包括:抽象、信息隱蔽、模塊化、局部化、確定性、一致性、完備性和可驗證性。

3.2 結構化分析方法

需求分析的任務是發現需求、求精、建模和定義需求的過程,可概括為:需求獲取、需求分析、編寫需求規格說明書和需求評審。

1.常用的分析方法

結構化分析方法:其實質著眼於數據流,自頂向下,逐層分解,建立系統的處理流程。

面向對象分析方法。

2.結構化分析常用工具

結構化分析常用工具包括數據流圖、數字字典(核心方法)、判斷樹和判斷表。

(1)數據流圖:即DFD圖,以圖形的方式描繪數據在系統中流動和處理的過程,它只反映系統必須完成的邏輯功能。是一種功能模型。

符號名稱作用:

箭頭代表數據流,沿箭頭方向傳送數據的通道

圓或橢圓代表加工,輸入數據經加工變換產生輸出

雙杠代表存儲文件,表示處理過程中存放各種數據文件

方框代表源和潭,表示系統和環境的介面

(2)數據字典:結構化分析方法的核心。數據字典是對所有與系統相關的數據元素的一個有組織的列表。以及精確的、嚴格的定義,使得用戶和系統分析員對於輸入、輸出、存儲成分和中間計算結果有共同的理解。

(3)判定樹:使用判定樹進行描述時,應先從問題定義的文字描述中分清判定的條件和判定的結論,根據描述材料中的連接詞找出判定條件之問的從屬關系、並列關系、選擇關系,根據它們構造判定樹。

(4)判定表:與判定樹相似,當數據流圖中的加工要依賴於多個邏輯條件的取值,即完成該加工的一組動作是由於某一組條件取值的組合引發的,使用判定表比較適宜。

3.軟體需求規格說明書

軟體需求規格說明書是需求分析階段的最後成果,是軟體開發的重要文檔之一。

(1)軟體需求規格說明書的作用:①便於用戶、開發人員進行理解和交流;②反映出用戶問題的結構,可以作為軟體開發工作的基礎和依據;③作為確認測試和驗收的依據。

(2)軟體需求規格說明書的內容:①概述;②數據描述;③功能描述;④性能描述;⑤參考文獻;⑥附錄。

(3)軟體需求規格說明書的特點:①正確性;②無歧義性;③完整性;④可驗證性;⑤一致性;⑥可理解性;⑦可修改性;⑧可追蹤性。

3.3 結構化設計方法

1.軟體設計的基本概念和方法

軟體沒計是一個把軟體需求轉換為軟體表示的過程。

(1)基本原理:抽象、模塊化、信息隱藏、模塊獨立性(度量標准:耦合性和內聚性,高耦合、低內聚)。

(2)基本思想:將軟體設計成由相對獨立、單一功能的模塊組成的結構。

2.概要設計

(1)4個任務:設計軟體系統結構、數據結構及資料庫設計、編寫概要設計文檔、概要設計文檔評審。

(2)面向數據流的設計方法:數據流圖的信息分為交換流和事物流,結構形式有交換型和事務型。

3.詳細設計的工具

詳細設計的工具包括:

圖形工具:程序流程圖、N-S、PAD、HIPO。

表格工具:判定表。

語言工具:PDL(偽碼)。

3.4 軟體測試

1.目的

為了發現錯誤而執行程序的過程。

2.准則

所有測試應追溯到用戶需求。

嚴格執行測試計劃,排除測試的隨意性。

充分注意測試中的群集現象。

程序員應避免檢查自己的程序。

窮舉測試不可能。

妥善保存設計計劃、測試用例、出錯統計和最終分析報告。

3.軟體測試技術和方法

軟體測試的方法按是否需要執行被測軟體的角度,可分為靜態測試和動態測試,按功能分為白盒測試和黑盒測試。

(1)白盒測試:根據程序的內部邏輯設計測試用例,主要方法有邏輯覆蓋測試、基本路徑測試等。

(2)黑盒測試:根據規格說明書的功能來設計測試用例,主要診斷方法有等價劃分法、邊界值分析法、錯誤推測法、因果圖法等,主要用於軟體確認測試。

4.軟體測試的實施

軟體測試是保證軟體質量的重要手段,軟體測試是一個過程,其測試流程是該過程規定的程序,目的是使軟體測試工作系統化。

軟體測試過程分4個步驟,即單元測試、集成測試、驗收測試和系統測試。

單元測試是對軟體設計的最小單位——模塊(程序單元)進行正確性檢驗測試。

單元測試的目的是發現各模塊內部可能存在的各種錯誤。

單元測試的依據是詳細的設計說明書和源程序。

單元測試的技術可以採用靜態分析和動態測試。

3.5 程序的調試

(1)任務:診斷和改正程序中的錯誤。

(2)調試方法:強行排錯法、回溯法和原因排除法。

第四章 資料庫設計基礎

4.1 資料庫系統的基本概念

(1) 數據(Data):描述事物的符號記錄。

(2) 資料庫(DataBase):長期存儲在計算機內的、有組織的、可共享的數據集合。

(3) 資料庫管理系統的概念

資料庫管理系統(DataBase Management System,DBMS)是資料庫的機構,它是一種系統軟體,負責資料庫中的數據組織、數據操作、數據維護、數據控制及保護和數據服務等。為完成以上6個功能,DBMS提供了相應的數據語言;數據定義語言(負責數據的模式定義與數據的物理存取構建);數據操縱語言(負責數據的操縱);數據控制語言(負責數據完整性、安全性的定義)。資料庫管理系統是資料庫系統的核心,它位於用戶和操作系統之間,從軟體分類的角度來說,屬於系統軟體。

(4) 資料庫技術發展經歷了3個階段。

人工管理階段→文件系統階段→資料庫系統階段

(5) 資料庫系統的特點:集成性、高共享性、低冗餘性、數據獨立性、數據統一管理與控制等。

(6) 資料庫系統的內部機構體系:三級模式(概念模式、內模式、外模式)和二級映射(外模式/概念模式的映射、概念模式/內模式的映射)構成了資料庫系統內部的抽象結構體系。

4.2 數據模型

數據模型是數據特徵的抽象,從抽象層次上描述了系統的靜態特徵、動態行為和約束條件,描述的內容有數據結構、數據操作和數據約束。有3個層次:概念數據模型、邏輯數據模型和物理數據模型。

(1) E—R模型:提供了表示實體、屬性和聯系的方法。實體間聯系有「一對一」、「一對多」和「多對多」。

(2) E-R模型用E-R圖來表示。

(3) 層次模型:利用樹形結構表示實體及其之問聯系。其中節點是實體,樹枝是聯系,從上到下是一對多關系。

(4) 網狀模型:用網狀結構表示實體及其之間聯系。是層次模型的擴展。網路模型以記錄型為節點,反映現實中較為復雜的事物聯系。

(5) 關系模型:採用二維表(由表框架和表的元組組成)來表示,可進行數據查詢、增加、刪除及修改操作。關系模型允許定義「實體完整性」、「參照完整性」和「用戶定義的完整性」三種約束。

鍵(碼):二維表中唯一能標識元組的最小屬性集。

候選鍵(候選碼):二維表中可能有的多個鍵。

主鍵:被選取的一個使用的鍵。

4.3 關系代數

(1) 關系代數的基本運算:投影、選擇、笛卡爾積。

(2) 關系代數的擴充運算:交、連接與自然連接、除。

4.4 資料庫設計與管理

1.資料庫設計概述

基本思想:過程迭代和逐步求精。

方法:面向數據的方法和面向過程的方法。

設計過程:需求分析→概念設計→邏輯設計→物理設計→編碼→測試→運行→進→步修改。

2.資料庫設計的需求分析

需求收集和分析是資料庫設計的第一階段,常用結構化分析方法(自頂向下、逐層分解)和面向對象的方法,主要工作有繪制數據流程圖、數據分析、功能分析、確定功能處理模塊和數據間關系。

數據字典:包括數據項、數據結構、數據流、數據存儲和處理過程,是對系統中數據的詳盡描述。

3.資料庫的設計

(1) 資料庫的概念設計:分析數據問內在的語義關聯,以建立數據的抽象模型。

(2) 資料庫的邏輯設計:從E-R圖向關系模型轉換,邏輯模式規范化,關系視圖設計可以根據用戶需求隨時創建。實體轉換為元組,屬性轉換為關系的屬性,聯系轉換為關系。

(3) 資料庫的物理設計:是數據在物理設備上的存儲結構與存取方法,目的是對資料庫內部物理結構作出調整並選擇合理的存取路徑,以提高速度和存儲空間。

4.資料庫管理

資料庫管理包括資料庫的建立、資料庫的調整、資料庫的重組、資料庫的安全性與完整性控制、資料庫故障恢復和資料庫的監控。

;

10. C語言指針難點高手請進… typedef int *p; p r; p &q=r; 這是怎麼理解

這是C++中容易讓人迷糊的一個知識點:
typedef int *p; p r; p &q=r;
這行按分號可分成三個語句,分別是
1 typedef int * p;
2 p r;
3 p &q=r;//int * &q=r
第一行其實可以寫成如下格式
typedef int* p;
這就容易看懂了 其實就是設定int *的別名為p,其他兩行的 類型p 其實也就是 int* 類型;所以第二行就是聲名了一個int類型的指針。第三行是聲名一個
指針類型的引用q, 並將r賦值給 q