《 C 語言的一些“騷操作”及其深層理解》之memcpy 的效率
memcpy的效率
memcpy函數(shù)的功能是用來作內存搬運,就是將數(shù)據(jù)從一個數(shù)組賦值到另一個數(shù)組。它的實現(xiàn)很簡單:
但是這種實現(xiàn)方式,其實是比較膚淺而低效的。作為嵌入式或硬件工程師,如果對上面的代碼看不出什么問題的話,那可能要好好找找自身的原因。
上面的代碼,對CPU數(shù)據(jù)總線帶寬的利用率不高,我們把它改成這樣:
改進后的代碼最大限度的利用了CPU數(shù)據(jù)總線帶寬,每次傳輸多個字節(jié)(如32位平臺為4字節(jié))。這一實例告訴我們:C語言,尤其是嵌入式C語言很多時候需要考慮硬件層面的因素,如CPU總線、內存結構等。
[]的本質
當我們想取出一個數(shù)組中的某個元素時,我們會用到[],采用下標的方式。如下例:
int a[3]={1,2,3};
a[1]; //數(shù)組a的第2個元素
其實我們可以用其它方式取出這個元素,即*(a+1)??梢钥吹絒]與*,在功能上有相似之處。其實[]并不限于與數(shù)組搭配訪問數(shù)組元素,它的實質是:訪問以指針所指向的地址為開始地址,以其下標為偏移量的存儲單元中的數(shù)據(jù),如圖2.12所示。
圖2.12 []的實質其實就是所謂的“基址偏移量取值”
上圖可能顛覆了一些人對[]的認識,下標還能是負數(shù)?[]可以在一個開始地址后面去取數(shù)據(jù),為什么不能在它前面取數(shù)據(jù)呢?我們可以理解[]是對指針加減和取值操作的綜合。
認清了[]的實質,再加上對C語言的精髓--指針深刻的理解,我們編程將會非常靈活,肆意揮灑。
#與##(串化與連接)
C語言中的#與##可能很多人都不了解,更沒有用過,因為在一般的教材上都沒有對它們的介紹。但是把它們用好了,也能使我們的代碼別有一番格調。
串化,在宏定義中#可以將宏參數(shù)轉換為字符串,即在宏參數(shù)的開頭和末尾添加引號。似乎有些雞肋,但是如果看到別人的代碼有用到串化的時候,我們需要能夠看懂。
再來看一下連接符##,它用來將參數(shù)和其它的內容連接起來,如下例:
#define CON1(a, b) a##e##b#define CON2(a, b) a##b##00
printf("%f\n", CON1(8.5, 2));printf("%d\n", CON2(12, 34));
printf("%f\n", 8.5e2); //展開后的效果
printf("%d\n", 123400); //展開后的效果
我在很多ARM官方評估板的配套代碼中看到過大量串化與連接的應用,當時我并不知道C語言還有串化連接這些東西(雖然我已經(jīng)用C語言有十幾年了),所以有些看不明白。通過百度學習了一下#與##,這才懂了。所以,C語言學得多精都不為過,很多知識我們可能一輩子都不會用到,但是不代表我們可以不知道,因為別人在用。
OK,關于C語言方面的一些常見問題、非常規(guī)操作以及認知誤區(qū)振南就講這么多。C語言其實是博大精深,還是那句話:“學得多精都不為過!”我一直把嵌入式工程師比喻成“能與硬件對話的靈媒”,我們所使用的語言就是C語言。我們自認為對C語言已經(jīng)足夠了解了,足夠精通了,但是我們又會發(fā)現(xiàn)在實際開發(fā)過程中,會遇到很多新的問題,很多問題是與C語言本身相關的。
所以記?。骸皩W海無涯!” 有C語言方面的問題,歡迎與振南來溝通交流,我自己也在不斷學習的過程中。