日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C程序优化之路(二)

發(fā)布時間:2023/12/9 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C程序优化之路(二) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
本文講述在編寫C程序代碼的常用優(yōu)化辦法,分為I/O篇,內存篇,算法篇,MMX匯編篇。

二.內存篇

?????? 在上一篇中我們講述了如何優(yōu)化文件的讀寫,這一篇則主要講述對內存操作的優(yōu)化,主要有數(shù)組的尋址,指針鏈表等,還有一些實用技巧。

I.優(yōu)化數(shù)組的尋址

?????? 在編寫程序時,我們常常使用一個一維數(shù)組a[M×N]來模擬二維數(shù)組a[N][M],這個時候訪問a[]一維數(shù)組的時候:我們經常是這樣寫a[j×M+i](對于a[j][i])。這樣寫當然是無可置疑的,但是顯然每個尋址語句j×M+i都要進行一次乘法運算。現(xiàn)在再讓我們看看二維數(shù)值的尋址,說到這里我們不得不深入到C編譯器在申請二維數(shù)組和一維數(shù)組的內部細節(jié)上――實際在申請二位數(shù)組和一維數(shù)組,編譯器的處理是不一樣的,申請一個a[N][M]的數(shù)組要比申請一個a[M×N]的數(shù)組占用的空間大!二維數(shù)組的結構是分為兩部分的:

① 是一個指針數(shù)組,存儲的是每一行的起始地址,這也就是為什么在a[N][M]中,a[j]是一個指針而不是a[j][0]數(shù)據(jù)的原因。

② 是真正的M×N的連續(xù)數(shù)據(jù)塊,這解釋了為什么一個二維數(shù)組可以象一維數(shù)組那樣尋址的原因。(即a[j][i]等同于(a[0])[j×M+i])

清楚了這些,我們就可以知道二維數(shù)組要比(模擬該二維數(shù)組的)一維數(shù)組尋址效率高。因為a[j][i]的尋址僅僅是訪問指針數(shù)組得到j行的地址,然后再+i,是沒有乘法運算的!

??? 所以,在處理一維數(shù)組的時候,我們常常采用下面的優(yōu)化辦法:(偽碼例子)

??? int a[M*N];
??? int *b=a;
??? for(…)
??? {
??????? b[…]=…;
??????? …………
??????? b[…]=…;
??????? b+=M;
??? }

這個是遍歷訪問數(shù)組的一個優(yōu)化例子,每次b+=M就使得b更新為下一行的頭指針。當然如果你愿意的話,可以自己定義一個數(shù)組指針來存儲每一行的起始地址。然后按照二維數(shù)組的尋址辦法來處理一維數(shù)組。不過,在這里我建議你干脆就直接申請一個二維數(shù)組比較的好。下面是動態(tài)申請和釋放一個二維數(shù)組的C代碼。

int get_mem2Dint(int ***array2D, int rows, int columns)???? //h.263源代碼
{
??? int i;

??? if((*array2D?= (int**)calloc(rows, sizeof(int*))) == NULL) no_mem_exit(1);
??? if(((*array2D)[0] = (int* )calloc(rows*columns,sizeof(int ))) == NULL) no_mem_exit(1);

for(i=1 ; i<rows ; i++)
??????? (*array2D)[i] =? (*array2D)[i-1] + columns? ;

return rows*columns*sizeof(int);
}

void free_mem2D(byte **array2D)
{
??? if (array2D)
??? {
??? ??? if (array2D[0])
??????????? free (array2D[0]);
??????? else
??????????? error ("free_mem2D: trying to free unused memory",100);

??????? free (array2D);
? ? }
??? else
??? {
??? ??? error ("free_mem2D: trying to free unused memory",100);
??? }
}

順便說一下,如果你的數(shù)組尋址有一個偏移量的話,不要寫為a[x+offset],而應該為?b=a+offset,然后訪問b[x]。

不過,如果你不是處理對速度有特別要求的程序的話,這樣的優(yōu)化也就不必要了。記住,如果編普通程序的話,可讀性和可移值性是第一位的。

II.從負數(shù)開始的數(shù)組

?????? 在編程的時候,你是不是經常要處理邊界問題呢?在處理邊界問題的時候,經常下標是從負數(shù)開始的,通常我們的處理是將邊界處理分離出來,單獨用額外的代碼寫。那么當你知道如何使用從負數(shù)開始的數(shù)組的時候,邊界處理就方便多了。下面是靜態(tài)使用一個從-1開始的數(shù)組:

int a[M];

int *pa=a+1;

現(xiàn)在如果你使用pa訪問a的時候就是從-1M2了,就是這么簡單。(如果你動態(tài)申請a的話,freea)可不要freepa)因為pa不是數(shù)組的頭地址)

III.我們需要鏈表嗎

?????? 相信大家在學習《數(shù)據(jù)結構》的時候,對鏈表是相當熟悉了,所以我看有人在編寫一些耗時算法的時候,也采用了鏈表的形式。這樣編寫當然對內存的占用(似乎)少了,可是速度呢?如果你測試:申請并遍歷10000個元素鏈表的時間與遍歷相同元素的數(shù)組的時間,你就會發(fā)現(xiàn)時間相差了百倍!(以前測試過一個算法,用鏈表是1分鐘,用數(shù)組是4秒鐘)。所以這里我的建議是:在編寫耗時大的代碼時,盡可能不要采用鏈表!

?????? 其實實際上采用鏈表并不能真正節(jié)省內存,在編寫很多算法的時候,我們是知道要占用多少內存的(至少也知道個大概),那么與其用鏈表一點點的消耗內存,不如用數(shù)組一步就把內存占用。采用鏈表的形式一定是在元素比較少,或者該部分基本不耗時的情況下。

(我估計鏈表主要慢是慢在它是一步步申請內存的,如果能夠象數(shù)組一樣分配一個大內存塊的話,應該也不怎么耗時,這個沒有具體測試過。僅僅是猜想 :P)

轉載于:https://www.cnblogs.com/huaping-audio/archive/2008/09/11/1289454.html

總結

以上是生活随笔為你收集整理的C程序优化之路(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。