精通C語言是有難度的它掂,卻也不是沒有方法巴帮。
首先溯泣,內(nèi)存意識。
C語言和其他高級語言不一樣榕茧,它的很多操作都是直接面向內(nèi)存(面向硬件)垃沦。
困難的是,對于C語言用押,不論是數(shù)據(jù)類型肢簿、操作符、語句蜻拨、函數(shù)池充,都或多或少、或簡單或復(fù)雜地通過地址操作內(nèi)存缎讼。
幸運的是收夸,一旦掌握內(nèi)存,代碼功能會非常強大血崭,執(zhí)行效率非常之高卧惜。
舉個例子。
如何把一個二進制數(shù)轉(zhuǎn)換成十進制以字符的形式輸出夹纫?
做過十進制位數(shù)分離的程序員都知道咽瓷,可以采取“模10再除10”的方法把一個二進制數(shù)按十進制分離每一位。
嘗試著去理解下面的程序舰讹。
while(putchar(value % 10 + '0') && (value /= 10))
;
putchar()函數(shù)的原型是int putchar(int ch);執(zhí)行結(jié)束返回1茅姜。
這個代碼風(fēng)格已經(jīng)算優(yōu)質(zhì)了,只不過這樣是倒序的月匣,想要實現(xiàn)正序排列可以使用遞歸匈睁。
void binary_to_ascii (unsigned int value)
{
unsigned int quotient;
quotient = value / 10;
if(quotient != 0)
binary_to_ascii(quotient);
putchar(value % 10 + '0');
}
但是當(dāng)你明白了字符串常量的原理后,你可能會寫出這樣不平凡的代碼桶错。
;
這是因為航唆,一個字符串常量存儲在內(nèi)存的某一位置,調(diào)用它的時候院刁,并沒有把整個字符串傳遞進去糯钙,而是只傳遞一個指針常量(一個地址),然后執(zhí)行和數(shù)組相同原理的下標引用退腥。沒錯任岸,你可能猜到了,也猜對了狡刘,數(shù)組名也是一個指針常量享潜。小編推薦一個學(xué)C語言/C++的學(xué)習(xí)裙【 六二七,零一二嗅蔬,四六四 】剑按,無論你是大牛還是小白疾就,是想轉(zhuǎn)行還是想入行都可以來了解一
起進步一起學(xué)習(xí)!裙內(nèi)有開發(fā)工具艺蝴,很多干貨和技術(shù)資料分享猬腰!
其次,掌握原理猜敢。
掌握哪些原理姑荷?數(shù)據(jù)類型、操作符是重點缩擂。
典型的鼠冕,指針、數(shù)組胯盯、結(jié)構(gòu)體供鸠、一些重點操作符。
以操作符為例:
++操作符:a++和++a它們的機制分別是什么陨闹?
a++:我們稱為后++楞捂,首先a生成一份拷貝,然后a執(zhí)行++趋厉,最后返回拷貝寨闹。返回的拷貝值是舊a,新a已經(jīng)執(zhí)行了++操作君账。
++a:我們稱為前++繁堡,首先a執(zhí)行++,然后a生成一份拷貝乡数,最后返回拷貝椭蹄。a先執(zhí)行++,再拷貝净赴,返回的拷貝就是新a绳矩。
如何理解拷貝?簡單學(xué)習(xí)匯編語言玖翅,了解機器內(nèi)部的運算方式翼馆,就可以理解。
&&和||操作符:先執(zhí)行左表達式金度,再執(zhí)行右表達式应媚,如果左表達式就能確定整個結(jié)果,則不執(zhí)行右表達式猜极。
如果你知道while語句和scanf()中姜、putchar()的原型,那么下面這個語句將不難理解跟伏。
while(scanf("%d", ch) && ch != EOF)
putchar(ch);
scanf()換成getchar()也可以丢胚,這里只是想提醒大家scanf()的原型翩瓜。
如果你足夠理解for語句和表達式,看下面這個代碼嗜桌。
int a[n], *vp;
for(vp = a; vp
*vp++ = 0;
}
這個代碼有兩個問題:功能是什么奥溺?是否有錯誤辞色?
第一個問題:功能是實現(xiàn)數(shù)組的初始化骨宠。
第二個問題:沒有錯誤。其一相满,&a[n]层亿,指向數(shù)組外,指向并不會有錯誤立美,但是不能執(zhí)行間接訪問匿又,即*vp=a[n]是非法的。其二建蹄,for語句碌更,括號內(nèi)需要三個表達式,最后一個不寫洞慎,表示空表達式痛单,空表達式也是表達式。
最后劲腿,清晰概念旭绒。
什么是預(yù)處理、什么是表達式焦人、什么是語句挥吵、什么是函數(shù)、什么是操作符花椭、什么是數(shù)據(jù)類型忽匈。
只有真正能區(qū)分它們的不同,你才能理解各種復(fù)雜的代碼矿辽。
p=&a和*p=&a脉幢,在一定的語句下,都可以是正確的嗦锐,它們又有什么不同嫌松?
什么是聲明、什么是定義奕污、什么是調(diào)用萎羔。
它們作用于不同的數(shù)據(jù)類型是否有本質(zhì)上的區(qū)別。
比如說碳默,聲明一個變量贾陷,就要分配內(nèi)存缘眶。聲明一個結(jié)構(gòu)體,不會分配內(nèi)存髓废,只有定義一個實體的時候巷懈,才分配。它們的實現(xiàn)原理不同慌洪,具體使用就會有細微的差別顶燕。
什么是常量、什么是變量冈爹、什么是指針常量char * cnost f涌攻、什么是常量指針char const *f、什么是指針函數(shù)char *f()频伤、什么是函數(shù)指針char (*f)()恳谎,等等。
區(qū)分它們憋肖,只有一個辦法因痛,掌握操作符優(yōu)先級,變量f先和什么結(jié)合岸更,f就是什么鸵膏,前面剩下的,就是返回類型坐慰。
char * cnost f:f是常量较性,并且是指針,返回類型為普通的char结胀。指針常量赞咙,指針的值不能變,指針指向的數(shù)據(jù)可變糟港,比如數(shù)組名攀操。
char const *f:f是普通的指針,返回類型是char const秸抚。指針的值可變速和,指針指向的數(shù)據(jù)不能變。常量指針剥汤,面向接口編程常用的方法颠放。
char *f():()的優(yōu)先級比*高,所以f是一個函數(shù)吭敢,返回類型是一個char型指針碰凶,返回類型為指針的函數(shù)。指針函數(shù),動態(tài)分配內(nèi)存的好方法欲低。
char (*f)():同為()辕宏,優(yōu)先級相同看結(jié)合性,自左向右砾莱。f是一個指針瑞筐,指向一個返回為char型的函數(shù)。函數(shù)指針腊瑟,回調(diào)函數(shù)的實現(xiàn)方法聚假。
掌握了上面的知識就能精通C語言么?
顯然是遠遠不夠的扫步,我只是從我的角度總結(jié)了幾個方面魔策,給出一些建議匈子。
而真正要做到精通河胎,只有不斷的學(xué)習(xí)。