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