精通C語言是有難度的,卻也不是沒有方法。
首先,內存意識。
C語言和其他高級語言不一樣,它的很多操作都是直接面向內存(面向硬件)。
困難的是,對於C語言,不論是數據類型、操作符、語句、函數,都或多或少、或簡單或復雜地通過地址操作內存。
幸運的是,一旦掌握內存,代碼功能會非常強大,執行效率非常之高。
舉個例子。
如何把一個二進制數轉換成十進制以字符的形式輸出?
做過十進制位數分離的程序員都知道,可以采取“模10再除10”的方法把一個二進制數按十進制分離每一位。
嘗試着去理解下面的程序。
while(putchar(value % 10 + '0') && (value /= 10))
;
putchar()函數的原型是int putchar(int ch);執行結束返回1。
這個代碼風格已經算優質了,只不過這樣是倒序的,想要實現正序排列可以使用遞歸。
void binary_to_ascii (unsigned int value)
{
unsigned int quotient;
quotient = value / 10;
if(quotient != 0)
binary_to_ascii(quotient);
putchar(value % 10 + '0');
}
但是當你明白了字符串常量的原理后,你可能會寫出這樣不平凡的代碼。
while(putchar( "0{{123456789:0}}" [value % 10] ) && (value /= 10))
;
這是因為,一個字符串常量存儲在內存的某一位置,調用它的時候,並沒有把整個字符串傳遞進去,而是只傳遞一個指針常量(一個地址),然后執行和數組相同原理的下標引用。沒錯,你可能猜到了,也猜對了,數組名也是一個指針常量。
其次,掌握原理。
掌握哪些原理?數據類型、操作符是重點。
典型的,指針、數組、結構體、一些重點操作符。
以操作符為例:
++操作符:a++和++a它們的機制分別是什么?
a++:我們稱為后++,首先a生成一份拷貝,然后a執行++,最后返回拷貝。返回的拷貝值是舊a,新a已經執行了++操作。
++a:我們稱為前++,首先a執行++,然后a生成一份拷貝,最后返回拷貝。a先執行++,再拷貝,返回的拷貝就是新a。
如何理解拷貝?簡單學習匯編語言,了解機器內部的運算方式,就可以理解。
&&和||操作符:先執行左表達式,再執行右表達式,如果左表達式就能確定整個結果,則不執行右表達式。
如果你知道while語句和scanf()、putchar()的原型,那么下面這個語句將不難理解。
while(scanf("%d", ch) && ch != EOF)
putchar(ch);
scanf()換成getchar()也可以,這里只是想提醒大家scanf()的原型。
如果你足夠理解for語句和表達式,看下面這個代碼。
int a[n], *vp;
for(vp = a; vp < &a[n]; ){
*vp++ = 0;
}
這個代碼有兩個問題:功能是什么?是否有錯誤?
第一個問題:功能是實現數組的初始化。
第二個問題:沒有錯誤。其一,&a[n],指向數組外,指向並不會有錯誤,但是不能執行間接訪問,即*vp=a[n]是非法的。其二,for語句,括號內需要三個表達式,最后一個不寫,表示空表達式,空表達式也是表達式。
最后,清晰概念。
什么是預處理、什么是表達式、什么是語句、什么是函數、什么是操作符、什么是數據類型。
只有真正能區分它們的不同,你才能理解各種復雜的代碼。
p=&a和*p=&a,在一定的語句下,都可以是正確的,它們又有什么不同?
什么是聲明、什么是定義、什么是調用。
它們作用於不同的數據類型是否有本質上的區別。
比如說,聲明一個變量,就要分配內存。聲明一個結構體,不會分配內存,只有定義一個實體的時候,才分配。它們的實現原理不同,具體使用就會有細微的差別。
什么是常量、什么是變量、什么是指針常量char * cnost f、什么是常量指針char const *f、什么是指針函數char *f()、什么是函數指針char (*f)(),等等。
區分它們,只有一個辦法,掌握操作符優先級,變量f先和什么結合,f就是什么,前面剩下的,就是返回類型。
char * cnost f:f是常量,並且是指針,返回類型為普通的char。指針常量,指針的值不能變,指針指向的數據可變,比如數組名。
char const *f:f是普通的指針,返回類型是char const。指針的值可變,指針指向的數據不能變。常量指針,面向接口編程常用的方法。
char *f():()的優先級比*高,所以f是一個函數,返回類型是一個char型指針,返回類型為指針的函數。指針函數,動態分配內存的好方法。
char (*f)():同為(),優先級相同看結合性,自左向右。f是一個指針,指向一個返回為char型的函數。函數指針,回調函數的實現方法。
掌握了上面的知識就能精通C語言么?
顯然是遠遠不夠的,我只是從我的角度總結了幾個方面,給出一些建議。
而真正要做到精通,只有不斷的學習。