學(xué)習(xí)完c語言一直想寫一個知識體系的東西,總感覺自己能力不夠,
淺談c語言的知識體系
。終于鼓起勇氣,來和大家聊聊我學(xué)習(xí)c語言的感悟。當(dāng)然,要在這幾千字中將c語言的所有知識點都遍歷一遍是不現(xiàn)實的,本人也不具備這樣的能力。我會在下面寫到我學(xué)習(xí)c語言的時候感覺重要的東西。一.選擇結(jié)構(gòu)程序設(shè)計以及循環(huán)結(jié)構(gòu)設(shè)計
1.if語句的使用
1).bool變量與“零值”比較
bool i = FALSE;
那么下面初始化什么比較好?
if( i == 0); if(i == 1) // 1 if( i == TURE); if( i == FALSE); //2 if(i); if(!i); //3
注意:大家知道if語句是靠其后面括號里表達(dá)式的值來進行分支跳轉(zhuǎn)。表達(dá)式為真,則執(zhí)行if語句后面緊跟的代碼;否則不執(zhí)行。那顯然,第三組寫法很好。不會引起誤會,也不會因為TRUE,FALSE的不同定義值而出錯。
當(dāng)然,還有float變量和“零值”比較。指針變量與“零值”比較。大家可以自己研究。我在這里就不再講述了。
2.while循環(huán)使用
1).講述一個例子來剖析一下吧
#include int main() { int a = 1; int b = 2; int c = 2; int t; while (a < b < c) { t = a; a = b; b = t; c--; } printf("%d %d", a, c); system("pause"); return 0; }
分析一下結(jié)果會是什么?a的值為1,c的值為0;while循環(huán)也關(guān)注的是括號里面的值是否為真,那么a
3.for循環(huán)的使用
同樣用一個例子來分析一下
#include int main() { int i = 0; int arr[10] = {0}; for (i = 0; i < 10; i++) { arr[i] = i; } for (i = 0; i < 10; i++) { printf("%d\n", arr[i]); } system("pause"); return 0; }
當(dāng)然這個程序是非常簡單,但足以說明問題。當(dāng)i = 10的時候會跳出循環(huán)。那么就很簡單明了了。當(dāng)然for循環(huán)也可以用while循環(huán)改寫。
二.數(shù)組
數(shù)組是儲存同一數(shù)據(jù)類型的一組有序的數(shù)據(jù)的集合。
數(shù)組中需要注意的點:
1.數(shù)組用循環(huán)語句賦值。同樣是上面的for循環(huán),可以自己試試將條件 i<10改為 i<11試試。程序會無條件的奔潰。因為你操作越界了,訪問了不屬于你自己的內(nèi)存。
2.數(shù)組下標(biāo)的操作。記住一點的就是,數(shù)組的下標(biāo)是從0開始,并不是1。!
3.數(shù)組和逗號表達(dá)式一起迷惑你。
#include int main() { int a[3][2] = { (0, 1), (2, 3), (4, 5) }; int *p = a[0]; printf("%d", p[0]); system("pause"); return 0; }
這個時候的p[0]等于1;為什么,不是應(yīng)該是0?這就考到了逗號表達(dá)式,逗號表達(dá)式最后一個值才是整個表達(dá)式的值,那么上面的代碼就變成了 int a[3][2] = {1,3,5};如果這樣說,你是不是就會做對呢?
4.二維數(shù)組在內(nèi)存中的存儲
假如二維數(shù)組
int arr[3][3] = {0};
二維數(shù)組在內(nèi)存中存儲是線性的。我們可以用一維數(shù)組的方式來理解二維數(shù)組,上述代碼代表的二維數(shù)組有三個元素,arr[0],arr[1],arr[2],同時每一個元素分別有三個元素,arr[0][0],arr[0][1],arr[0][2]...,那么可以這樣理解arr[0],arr[1],arr[2],就是一維數(shù)組的數(shù)組名,只不過這三個一維數(shù)組是有聯(lián)系的并且在內(nèi)存中是連續(xù)開辟的。
同理我們可以推到三維數(shù)組直到n維數(shù)組。只要你有時間并且有毅力和決心(意義不大)。哈哈。
5.字符數(shù)組
字符數(shù)組的賦值方式,為什么要提字符數(shù)組的賦值方式,本人認(rèn)為這和字符串的操作息息相關(guān),看看兩種不同的賦值方式。
1).
char arr[]={'i',' ','a','m',' ','h','a','c','k','e','r'};
可以預(yù)見的是,沒有‘\0’;那么這個字符數(shù)組所儲存的字符串是不會使用一系列的字符串操作函數(shù),
電腦資料
《淺談c語言的知識體系》(http://www.msguai.com)。如果對常見的字符串操作函數(shù)不太了解,那么訪問下面的鏈接,http://10799170.blog.51cto.com/10789170/1715083 幫助你了解常見的字符串操作函數(shù)的實現(xiàn)與注意的事項。言歸正傳,第二種賦值方式。2).
char arr[] = "i am hacker";
這種賦值方式,是最常見也是經(jīng)的起考驗,建議大家就這樣使用字符數(shù)組的賦值。這種賦值方式不會丟掉“\0”。那么,問題來了,可不可以這樣賦值?
char arr[] = {"i am hacker"}; char arr[] { = "i am hacker"};
答案是肯定的,有興趣的讀者可以在《c語言深度剖析》第二章第6小節(jié)看到。
6.總結(jié)一下:
1).自己給數(shù)組在內(nèi)存中賦值的時候,千萬注意內(nèi)存越界的問題。
2).數(shù)組的下標(biāo)操作。
3).字符數(shù)組的“\0”。
4).二維數(shù)組的賦值方式,理解方式以及使用方式。
三.指針
指針是地址。我在初學(xué)指針的時候,總是分不清楚,指針和指針變量和它指向的地址中的內(nèi)容的區(qū)別,所幸,我在鉆研了一下午理解了指針這個東西。得益于一本叫做《c和指針》的書,里面講述的清楚易懂。
1.一級指針
定義一個一級指針
1
int *p = NULL;
首先要說的是,指針就是地址,指針變量就是用來保存指針指向的那塊空間的地址,“*”就是打開這塊內(nèi)存的鑰匙。其次,指針的定義和賦值是兩碼事,不可以混為一談。最后我也曾經(jīng)寫過自己對指針,數(shù)組指針的理解。讀者有興趣可以打開下面的鏈接
1).指針的笑話(在vc6.0中實現(xiàn))
int *p = (int *)ox12ff7c; //這個地址必須是內(nèi)存開始給變量分配地址的第一個,要不是 //不會有作用! *p = NULL; p = NULL;
讀者可以自己試試結(jié)果是什么。
2).談?wù)勚羔樀陌踩?/p>
指針是可以指向內(nèi)存中的任何地址的,但是在一個程序中,總是只有自己的棧幀,或者儲存在靜態(tài)去和堆上的內(nèi)存。如果一不小心訪問到不屬于自己的內(nèi)存,并改掉其中的值。對于一個大型程序來說,調(diào)試都是一個非常龐大的工作。所以,在使用指針的時候千萬要小心。杜絕野指針!!
3).const和assert修飾指針
不需要修改指針指向的值,請必須加上const修飾
const int *p; int const *p; int * const p; const int * const p;
讀者可以嘗試著分析上面的語句代表著什么。
assert只在debug版本生效,在release版本沒有意義。在debug版本可以幫助我們檢驗指針的有效性。大公司面試的時候很注重這一定。
自己在學(xué)習(xí)的時候看的書是《c語言深度剖析》和《c和指針》。讀者可以自己進一步了解。
四.內(nèi)存操作
說到內(nèi)存操作,不得不提到棧幀。讀者可以參考我原來寫過的一片博文 附上url
http://10799170.blog.51cto.com/10789170/1715186
那么我們在這里就主要討論討論malloc開辟內(nèi)存時應(yīng)該注意的問題。
1).動態(tài)開辟內(nèi)存后,需要判斷內(nèi)存是否開辟成功。
如果內(nèi)存沒有開辟成功,我們直接使用會造成訪問越界;
2).在使用完成后必須使用free函數(shù)釋放掉內(nèi)存,其原理是將指針與內(nèi)存切斷聯(lián)系。
會造成內(nèi)存泄漏。很危險!
3).使用完成后指針應(yīng)賦為NULL;杜絕野指針。
沒有及時將指針賦值為NULL,指針會指向“垃圾”內(nèi)存!
五.函數(shù)
函數(shù)這一部分,本來是不愿意拿出來說的,畢竟每一個學(xué)習(xí)c語言的人,幾乎都在寫函數(shù)。那么我們就總結(jié)一下函數(shù)的好處吧。
1).降低復(fù)雜性
2).避免重復(fù)代碼
3).限制改動帶來的影響。
4).隱含順序
5).改進性能
6).進行集中控制
讀者需要了解請參照《c語言深度剖析》。
六.結(jié)構(gòu)體
說說我對結(jié)構(gòu)體的感悟吧,不再談?wù)Z法。
1.結(jié)構(gòu)體是一個自定義的類型,可以用這個類型定義結(jié)構(gòu)體變量。
2.結(jié)構(gòu)體不同于數(shù)組,它可以將集中不同的數(shù)據(jù)類型集中在一起。
3.是實現(xiàn)鏈表的結(jié)點。
4.本人用結(jié)構(gòu)體實現(xiàn)過一個簡易的電話本,附上url