讓你的 C 程序更有效率的 10 種方法

2021-01-11 開源中國

任何代碼的美麗不僅在於找到一個給定的問題的解決方案,但在它的簡單性,有效性,緊湊性和效率(內存)。設計的代碼比實際執行更難 。因此,每一個程式設計師當用C語言開發時,都應該保持這些基本的東西在頭腦中。

  本文向你介紹規範你的C代碼的10種方法。

1. 避免不必要的函數調用

考慮下面的2個函數:

void str_print( char *str )
{
    int i;
    for ( i = 0; i < strlen ( str ); i++ ) {
        printf("%c",str[ i ] );
    }
}

void str_print1 ( char *str )
{
    int len;
    len = strlen ( str );
    for ( i = 0; i < len; i++ ) {
        printf("%c",str[ i ] );
    }
}

請注意 這兩個函數的功能相似。然而,第一個函數調用strlen()函數多次,而第二個函數隻調用函數strlen()一次。因此第一個函數性能明顯比第二個好。

2、避免不必要的內存引用

這次我們再用2個例子來對比解釋:

int multiply ( int *num1 , int *num2 )
{
    *num1 = *num2;
    *num1 += *num2;
    return *num1;
} int multiply1 ( int *num1 , int *num2 )
{
    *num1 = 2 * *num2;
    return *num1;
}

同樣,這兩個函數具有類似的功能。所不同的是在第一個函數( 1 for reading *num1 , 2 for reading *num2 and 2 for writing to *num1)有5個內存的引用,而在第二個函數是只有2個內存引用(one for reading *num2 and one for writing to *num1)。現在你認為哪一個好些?

3、節約內存(內存對齊和填充的概念)

struct {
    char c;
    int i;
    short s;
}str_1;

struct {
    char c;
    short s;
    int i;
}str_2;

假設一個字符需要1個字節,short佔用2個字節和int需要4位元組的內存。起初,我們會認為上面定義的結構是相同的,因此佔據相同數量的內存。然而,而str_1佔用12個字節,第二個結構只需要8個字節?這怎麼可能呢?

請注意,在第一個結構,3個不同的4個字節被分配到三種數據類型,而在第二個結構的前4個自己char和short可以被採用,int可以採納在第二個的4個字節邊界(一共8個字節)。

4、使用無符號整數,而不是整數的,如果你知道的值將永遠是否定的。

 有些處理器可以處理無符號的整數比有符號整數的運算速度要快。(這也是很好的實踐,幫助self-documenting代碼)。

5、在一個邏輯條件語句中常數項永遠在左側。

int x = 4;
if ( x = 1 ) {
    x = x + 2;
    printf("%d",x);          // Output is 3
}

int x = 4;
if ( 1 = x ) {
    x = x + 2;
    printf("%d",x);   // Compilation error
}

使用「=」賦值運算符,替代「==」相等運算符,這是個常見的輸入錯誤。 常數項放在左側,將產生一個編譯時錯誤,讓你輕鬆捕獲你的錯誤。註:「=」是賦值運算符。 b = 1會設置變量b等於值1。 「==」相等運算符。如果左側等於右側,返回true,否則返回false。

6、在可能的情況下使用typedef替代macro。當然有時候你無法避免macro,但是typedef更好。

typedef int* INT_PTR;
INT_PTR a , b;
# define INT_PTR int*;
INT_PTR a , b;

在這個宏定義中,a是一個指向整數的指針,而b是只有一個整數聲明。使用typedef a和b都是 整數的指針。

7、確保聲明和定義是靜態的,除非您希望從不同的文件中調用該函數

在同一文件函數對其他函數可見,才稱之為靜態函數。它限制其他訪問內部函數,如果我們希望從外界隱藏該函數。現在我們並不需要為內部函數創建頭文件,其他看不到該函數。

靜態聲明一個函數的優點包括:

A)兩個或兩個以上具有相同名稱的靜態函數,可用於在不同的文件。

B)編譯消耗減少,因為沒有外部符號處理。

讓我們做更好的理解,下面的例子:


/*first_file.c*/
static int foo ( int a )
{
/*Whatever you want to in the function*/
}
/*second_file.c*/
int foo ( int )
int main()
{
    foo();      // This is not a valid function call as the function foo can only be called by any other function within first_file.c where it is defined.
    return 0;
}

8、使用Memoization,以避免遞歸重複計算

考慮Fibonacci(斐波那契)問題;Fibonacci問題是可以通過簡單的遞歸方法來解決:

int fib ( n )
{
    if ( n == 0 || n == 1 ) {
        return 1;
    }
    else {
        return fib( n - 2 ) + fib ( n - 1 );
    }
}

註:在這裡,我們考慮Fibonacci 系列從1開始,因此,該系列看起來:1,1,2,3,5,8,...

注意:從遞歸樹,我們計算fib(3)函數2次,fib(2)函數3次。這是相同函數的重複計算。如果n非常大,fib<n(i)函數增長i<n。解決這一問題的快速方法將是計算函數值1次,存儲在一些地方,需要時計算,而非一直重複計算。

這個簡單的技術叫做Memoization,可以被用在遞歸,加強計算速度。

fibonacci 函數Memoization的代碼,應該是下面的這個樣子:

int calc_fib ( int n )
{
    int val[ n ] , i;
    for ( i = 0; i <=n; i++ ) {
        val[ i ] = -1;         // Value of the first n + 1 terms of the fibonacci terms set to -1
    }
    val[ 0 ] = 1;                 // Value of fib ( 0 ) is set to 1
    val[ 1 ] = 1;            // Value of fib ( 1 ) is set to 1
    return fib( n , val );
}
int fib( int n , int* value )
{
    if ( value[ n ] != -1 ) {
        return value[ n ];              // Using memoization
    }
    else {
        value[ n ] = fib( n - 2 , value ) + fib ( n - 1 , value );          // Computing the fibonacci term
    }
    return value[ n ];                // Returning the value
}

這裡calc_fib( n )函數被main()調用。

9、避免懸空指針和野指針

一個指針的指向對象已被刪除,那麼就成了懸空指針。野指針是那些未初始化的指針,需要注意的是野指針不指向任何特定的內存位置。

void dangling_example()
{
    int *dp = malloc ( sizeof ( int ));
    /*........*/
    free( dp );              // dp is now a dangling pointer
    dp = NULL;        // dp is no longer a dangling pointer
}

void wild_example()
{
    int *ptr;        // Uninitialized pointer
    printf("%u"\n",ptr );
    printf("%d",*ptr );
}

當遭遇這些指針,程序通常是」怪異「的表現。

10、 永遠記住釋放你分配給程序的任何內存。上面的例子就是如果釋放dp指針(我們使用malloc()函數調用)。

原文:http://www.fortystones.com/tips-to-make-c-program-effective/

相關焦點

  • 這10個小技巧讓你讀書更有效率
    科學家實證的10個小技巧:讓你讀書更有效率Our brain can potentially memorize 2.5 petabytes of information, which is roughly the
  • 工具:C 程序轉換ShellCode利器
    三、功能Donut是一個ShellCode生成工具,可以將.NET程序集轉換為ShellCode。這是對Execute-Assembly的進一步利用,隱蔽性更高,可擴展性更強。這個donut程序的版本是0.93,可以將Exe、Dll、Vbs、Js轉換成ShellCode。
  • 為了更有效率地看書,我看了10本關於看書的書
    當你掌握這些基向量知識後,你會更加輕鬆,更有效率地吸納相關領域的新知識。為了更有效率,更快地把握書籍重點,書中精華,我先讀了十本關於如何讀書的書:《麥肯錫精英高效閱讀法》《如何閱讀一本書:超實用筆記讀書法》《認知天性:讓學習輕而易舉的心理學規律》《秋葉:如何高效讀懂一本書》《這樣讀書就夠了》《如何閱讀一本書》《讀懂一本書:樊登讀書法》《把時間當做朋友》《如何有效閱讀》《思維導圖筆記整理術》上面這些書從各種維度,不同方向地講解讀書這件事應該怎麼去做更好
  • 魚類的雜交育種操作程序及方法
    魚類的雜交育種操作程序及方法 中國漁業報2017-09-18 09:50:53 閱讀(2410)
  • 增強家用WiFi信號的10種方法 教你怎麼保養你的路由器
    若是你飽嘗速度慢、信號差等等摧殘,能夠參考一下這10種加強家用信號的方法。 快來看看360常識網下文所敘說的方法吧。加強家用WiFi信號的10種辦法1、運用最新Wi-Fi技術。 確保網絡高速暢通的一種方法即是運用最新的固件。
  • 2014年10月成人自考計算機基礎與程序設計真題
    ||5.若有下面程序段,欲使a=2,b=3,對應正確的數據輸入方法是(其中﹤CR﹥表示換行)int a,b;scanf('a=%d   b=%d',&a,&b);( )A.2﹤CR﹥B.a=2 b=3﹤CR﹥C.a=2,b=3﹤CR﹥D.2,3﹤CR﹥ 3﹤CR﹥6.下面程序段的輸出結果是( )main
  • 推薦最有效率的讀書的方法
    為了有效率的讀書,首先必須拋棄「書本只要精讀一冊」的觀念。只要閱讀自己所需信息的那  幾頁,閱讀書本的目的即已算達到了。例如,有一個問題你無法理解,當你拿到能獲得解答的參考書時,  根本就不必從最初的一頁開始閱讀,你一定會翻到解答的那一頁,且只閱讀這一頁。一旦獲得了必要的  信息,再閱讀這以外的部分,將構成時間的浪費。
  • 新愛滋病疫苗有效率最高可達80% 上市還需10年
    新愛滋病疫苗有效率最高可達80% 上市還需較長時間  國際在線專稿:據路透社報導,愛滋病防範研究已經過去25年,科學家們近日終於找到了一種可以對抗該疾病的疫苗,目前更深入的研究正在進行中。
  • 如何利用單片機高級C語言編制應用程式
    3系統功能程序設計 系統程序有以下部分組成:主程序、存取程序、監控管理程序、控制輸出程序、櫃體箱位排序程序及鍵盤中斷、時鐘定時中斷和報警程序下面主要介紹箱位排序程序、存取程序和防止密碼重複程序。軟體設計採用了模塊化結構設計方法,所有程序採用單片機高級C語言編寫。 主程序完成各個外設接口初始化,然後,進入鍵盤採樣處理顯示程序,由時鐘中斷程序完成顯示掃描更新及採樣處理。下面是箱位號初始化子程序。
  • switch動物之森雜交花攻略 教你種出奇異花朵
    switch動物之森雜交花攻略,相信很多玩家都清楚,如果我們平時用水壺澆花的話,有一定的機率會產出新的花種的,例如紫色的玫瑰花、橘色風信子、粉色菊花等等,但是想要培養出這些稀缺的花朵可不是一件容易的事,下面就讓小編來教大家如何種出奇異花朵吧.
  • 漲知識|21種方法讓你變聰明
    下面小編給大家介紹21種能夠讓你變聰明的方法,但是能否真的讓自己發生實質性的改變,那就因人而異了!畢竟,知道方法是不夠的,養成好規律,貴在堅持很重要!1.多玩猜謎。2.多運動。3.讀各類新聞。4.讓手機想休息一會。不斷查看手機會分散注意力,降低自己的工作效率。5.睡覺。
  • 科普:微信小程序二維碼生成的4種方法
    有這三種方法:方法一:登錄微信公眾平臺,輸入自己小程序的帳號密碼(沒有的話要先註冊一個小程序帳號),進入後臺主頁面,在左側菜單欄中找到【設置】,你會看到「小程序碼及線下物料下載」,這裡選擇你需要的尺寸和顏色,就能直接下載你的小程序碼。方法二:要想有一個小程序碼,你首先得有自己的小程序。
  • 養殖魚類的雜交育種操作程序及方法
    中國水產頻道報導,    一、雜交育種的意義    以雜交方法培育優良品種,或利用雜種優勢稱為雜交育種。雜交可以使生物的遺傳物質從一個群體轉移到另一群體,是增加生物變異性的一個重要方法。    2.複合雜交    兩個以上的品種,經兩次以上雜交的育種方法。如果單交不能實現育種所期待的性狀要求時,往往就採用複合雜交,其目的在於創造一些具有豐富遺傳基礎的雜種原始群體,才可能從中選出更優秀的個體。    複合雜交可分為三交、雙交等。
  • 51單片機100內的加減乘除計算器C語言程序
    #include //包含文件 #define uchar unsigned char #define uint unsigned int char b[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6, 0xa1,0x86,0x8e,0x8c,0xc1,0xce,0x91,0x89,0xc7,0xff
  • 機器學習之確定最佳聚類數目的10種方法
    在聚類分析的時候確定最佳聚類數目是一個很重要的問題,比如kmeans函數就要你提供聚類數目這個參數,總不能兩眼一抹黑亂填一個吧。之前也被這個問題困擾過,看了很多博客,大多泛泛帶過。今天把看到的這麼多方法進行匯總以及代碼實現並儘量弄清每個方法的原理。
  • 華氏溫度換算公式及C語言轉換程序代碼
    1714年他發現液體金屬水銀比酒精更適宜製造溫度計,以水銀為測溫介質,發明了玻璃水銀溫度計,選取氯化銨和水的混合物的冰點溫度(即氨水結冰的溫度)為溫度計的零度,人體溫度為溫度計的100度。在標準大氣壓下,冰的熔點為32℉,水的沸點為212℉,中間有180等分,每等分為華氏1度,記作「1℉」。「華氏溫標」是經驗溫標之一。在美國的日常生活中,多採用這種溫標,用字母「℉」表示。
  • 如何做事更有效率?諾森德日常任務攻略大全
    如何做事更有效率?諾森德日常任務攻略大全 2010/10/9 10:55:26    作者:誰敢比我醜    文章來源:本站原創   責任編輯:numb
  • 在R中子集化數據框的5種方法
    由於微信不允許外部連結,你需要點擊文章尾部左下角的 "閱讀原文",才能訪問文中連結。通常,我們在使用大型數據集時,只會對其中的一小部分感興趣,用以進行特定分析。 那麼,我們應該如何對所有無關的變量和觀察值進行排序並僅提取我們需要的那部分數據? 其實,在 R 中有幾種被稱為 「subsetting(子集化)」 的方法可以滿足以上的需求,今天我們來聊一下。
  • 每天花10分鐘讓你更快樂的8種方法
    而大雄今天整理的10分鐘習慣就能夠幫忙調整你的心態。1、三次「謝謝」感謝的能力是快樂的人的一個顯著特徵。習慣每天三次真誠地說「謝謝」,你可以把它給朋友、家人、愉快的事件或天氣。短短幾分鐘時間的感激之情,讓你回想起它的美好,讓你振奮起來,教會你在乍看之下欣賞無法察覺的美好時刻。
  • C語言程序設計試題與答案B卷
    A)本程序的main函數開始,到main函數結束 B)本程序文件的第一個函數開始,到本程序文件的最後一個函數結束C)本程序的main函數開始,到本程序文件的最後一個函數結束D)本程序文件的第一個函數開始,到本程序main函數結束