1. 程式人生 > >高效C語言技巧

高效C語言技巧

原文:https://blog.csdn.net/wangliang888888/article/details/51302375

一段完美的程式碼不僅在於找到一個給定的問題的解決方案,但在它的簡單性,有效性,緊湊性和效率(記憶體)。設計的程式碼比實際執行更難。因此,每一個程式設計師當用C語言開發時,都應該保持這些基本的東西在頭腦中。本文向你介紹規範你的C程式碼的幾種方法。

1、在可能的情況下使用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都是整數的指標。

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

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。

3、確保宣告和定義是靜態的,除非您希望從不同的檔案中呼叫該函式。

在同一檔案函式對其他函式可見,才稱之為靜態函式。它限制其他訪問內部函式,如果我們希望從外界隱藏該函式。現在我們並不需要為內部函式建立標頭檔案,其他看不到該函式。靜態宣告一個函式的優點包括:

(1)兩個或兩個以上具有相同名稱的靜態函式,可用於在不同的檔案。

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

4、節約記憶體(記憶體對齊和填充的概念)

struct  {  char c; int i; 

short s;}str_1;  

struct  { char c; shorts; inti;}str_2; 

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

請注意,在第一個結構,3個不同的4個位元組被分配到三種資料型別,而在第二個結構的前4個自己char和short可以被採用,int可以採納在第二個的4個位元組邊界(一共8個位元組)

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

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

6、switch-case語句。在程式中經常會使用switch-case語句,每一個由機器語言實現的測試和跳轉僅僅是為了決定下一步要做什麼,就浪費了處理器時間。為了提高速度,可以把具體的情況按照它們發生的相對頻率排序。即把最可能發生的情況放在第一,最不可能發生的情況放在最後,這樣會減少平均的程式碼執行時間。

當switch語句中的case標號很多時,為了減少比較的次數,明智的做法是把大switch語句轉為巢狀switch語句。把發生頻率高的case標號放在一個switch語句中,並且是巢狀switch語句的最外層,發生相對頻率相對低的case標號放在另一個switch語句中。比如,下面的程式段把相對發生頻率低的情況放在預設的case標號內。

pMsg=ReceiveMessage();

switch (pMsg->type)

{

case FREQUENT_MSG1:

handleFrequentMsg();

break;

case FREQUENT_MSG2:

handleFrequentMsg2();

break;

......

case FREQUENT_MSGn:

handleFrequentMsgn();

break;

default: //巢狀部分用來處理不經常發生的訊息

switch (pMsg->type)

{

case INFREQUENT_MSG1:

handleInfrequentMsg1();

break;

case INFREQUENT_MSG2:

handleInfrequentMsg2();

break;

......

case INFREQUENT_MSGm:

handleInfrequentMsgm();

break;

}

}

如果switch中每一種情況下都有很多的工作要做,那麼把整個switch語句用一個指向函式指標的表來替換會更加有效,比如下面的switch語句,有三種情況:

enum MsgType{Msg1, Msg2, Msg3}

switch (ReceiveMessage())

{

case Msg1;......

case Msg2;.....

case Msg3;.....

}

為了提高執行速度,用下面這段程式碼來替換這個上面的switch語句

/*準備工作*/

int handleMsg1(void);

int handleMsg2(void);

int handleMsg3(void);

/*建立一個函式指標陣列*/ 

int (*MsgFunction [])()={handleMsg1, handleMsg2, handleMsg3};

/*用下面這行更有效的程式碼來替換switch語句*/

status=MsgFunction[ReceiveMessage()]();

7、全域性變數。使用全域性變數比向函式傳遞引數更加有效率,這樣做去除了函式呼叫前引數入棧和函式完成後引數出棧的需要。當然,使用全域性變數會對程式有一些負作用。使用全域性變數比函式傳遞引數更加有效率。這樣做去除了函式呼叫引數入棧和函式完成後引數出棧所需要的時間。然而決定使用全域性變數會影響程式的模組化和重入,故要慎重使用。

8、嵌入式系統程式設計應避免使用標準庫例程,因為很多大的庫例程設法處理所有可能的情況,所以佔用了龐大的記憶體空間,因而應儘可能地減少使用標準庫例程。

9、Inline函式。在C++中,關鍵字Inline可以被加入到任何函式的宣告中。這個關鍵字請求編譯器用函式內部的程式碼替換所有對於指出的函式的呼叫。這樣做在兩個方面快於函式呼叫。這樣做在兩個方面快於函式呼叫:第一,省去了呼叫指令需要的執行時間;第二,省去了傳遞變元和傳遞過程需要的時間。但是使用這種方法在優化程式速度的同時,程式長度變大了,因此需要更多的ROM。使用這種優化在Inline函式頻繁呼叫並且只包含幾行程式碼的時候是最有效的。

10、用指標代替陣列。在許多種情況下,可以用指標運算代替陣列索引,這樣做常常能產生又快又短的程式碼。與陣列索引相比,指標一般能使程式碼速度更快,佔用空間更少。使用多維陣列時差異更明顯。下面的程式碼作用是相同的,但是效率不一樣。

陣列索引                     指標運算

For(;;){                         p=array      

A=array[t++];              for(;;){

                                     a=*(p++); 

......                               ......  

}

指標方法的優點是,array的地址每次裝入地址p後,在每次迴圈中只需對p增量操作。在陣列索引方法中,每次迴圈中都必須進行基於t值求陣列下標的複雜運算。

11、不定義不使用的返回值。function函式定義並不知道函式返回值是否被使用,假如返回值從來不會被用到,應該使用void來明確宣告函式不返回任何值。

12、手動編寫彙編。在嵌入式軟體開發中,一些軟體模組最好用匯編語言來寫,這可以使程式更加有效。雖然C/C++編譯器對程式碼進行了優化,但是適當的使用內聯彙編指令可以有效的提高整個系統執行的效率。

13、使用暫存器變數。在宣告區域性變數的時候可以使用register關鍵字。這就使得編譯器把變數放入一個多用途的暫存器中,而不是在堆疊中,合理使用這種方法可以提高執行速度。函式呼叫越是頻繁,越是可能提高程式碼的速度。

14、使用增量和減量操作符。在使用到加一和減一操作時儘量使用增量和減量操作符,因為增量符語句比賦值語句更快,原因在於對大多數CPU來說,對記憶體字的增、減量操作不必明顯地使用取記憶體和寫記憶體的指令,比如下面這條語句:x=x+1;

 模仿大多數微機組合語言為例,產生的程式碼類似於:

move A,x ;把x從記憶體取出存入累加A

add A,1 ;累加器A加1     

store x  ;把新值存回x 

如果使用增量操作符,生成的程式碼下:

incr x ;x加1 

顯然,不用取指令和存指令,增、減量操作執行的速度加快,同時長度也縮短了。

相關推薦

高效C語言技巧

原文:https://blog.csdn.net/wangliang888888/article/details/51302375一段完美的程式碼不僅在於找到一個給定的問題的解決方案,但在它的簡單性,有效性,緊湊性和效率(記憶體)。設計的程式碼比實際執行更難。因此,每一個程式

高效c語言 記憶體拷貝. 測試結果 rand, loop, operator= % in x86-64 SUSE

If you  use C++,C, when a  memory copy  is needed.   Please  Use    memcpy.    That will be very  very  very  fast!!!! if you are wonderi

很酷的C語言技巧,特別是第2個

C語言常常讓人覺得它所能表達的東西非常有限。它不具有類似第一級函式和模式匹配這樣的高階功能。但是C非常簡單,並且仍然有一些非常有用的語法技巧和功能,只是沒有多少人知道罷了。 指定的初始化 很多人都知道像這樣來靜態地初始化陣列: 1

C99中很酷的C語言技巧

C語言常常讓人覺得它所能表達的東西非常有限。它不具有類似第一級函式和模式匹配這樣的高階功能。但是C非常簡單,並且仍然有一些非常有用的語法技巧和功能,只是沒有多少人知道罷了。 指定的初始化 很多人都知道像這樣來靜態地初始化陣列: intfibs[] = {1, 1

這10個C語言技巧讓初學者少走180天彎路!

數控 對比 遞增 adf 一切都 人員 ima 檢測 處理 硬件設計師最常見的工作內容是通過寫代碼來測試硬件。這10個C語言技巧(C語言仍然是常見的選擇)可以幫助設計師避免因基礎性錯誤而導致某些缺陷的產生並造成維護方面的困擾。 技巧 1:不要使用“GOTO”語句 二十幾年前

C語言宏定義技巧——多次包括頭文件內容不同

ear 文件 我們 art bsp enum class 包括 nbsp 1、 頭文件定義例如以下: /* declears in “funcs.h” */ FUNC_1(ID_FUN1_001) FUNC_1(ID_FUN1_002) FUNC_2(ID_FUN2_

C語言高效編程的幾招(絕對實用,絕對經典)

n) 工程 fine bit 高效 nbsp 與運算 測試的 body 編寫高效簡潔的C語言代碼,是許多軟件工程師追求的目標。廢話不說,走起! 第一招:以空間換時間 計算機程序中最大的矛盾是空間和時間的矛盾,那麽,從這個角度出發逆向思維來考慮程序的效率問題 eg.字

C語言-第36課 - 函數遞歸與函數設計技巧

分而治之 andro 相同 tchar sse family tdi char s pri 第36課 - 函數遞歸與函數設計技巧 一. 遞歸 遞歸概述 (1) 遞歸是數學領域中的概念在程序設計中的應用。 (2) 遞歸是一種強有力的程序設計的方法。 (3) 遞歸的本質

高效記憶體池的設計方案 C語言

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

C語言迴圈及定義子函式技巧

最近在網上看到一段程式碼,感覺很有收穫,他簡化了函式宣告的過程,並且使程式實現部分可迴圈,不用每次都退出重新進 #include<stdio.h> int main() { int ctu=0; do { double Legendre(int,float); int n;float x; pr

C語言高效素數打表

埃式篩法素數打表 const int maxn = 10000; int vis[maxn]; int prim[maxn]; void fun() { int i, j; vis[0] = vis[1] = 1;//0,1是非素數 vis[2] = 0; int cnt =

資料結構--C語言--已知線性表中的元素以值遞增有序排列,並以單鏈表作儲存結構。試寫一高效演算法,刪除表中所有值大於mink且小於maxk的元素

#include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 #define LEN sizeof(struct LNode) struct LNode{ int data;//資料域 struct

海天醬油教你不知道的C語言程式設計技巧

在C語言程式設計中,我們經常會遇到這種情況,在某個函式中經過演算法處理以後得到一個字串型別的結果,可能需要將這個字串以指標的形式進行返回,那麼如何在函式中正確返回該字串的內容呢? 例如,定義一個函式,要求該函式能夠返回一個指向字串“I love C.”的指標並能在主程式中正確得到該字串的內容

C語言為什麼高效

C語言在現在的軟體開發中雖然用的不多,但是C語言在底層的用處一直其中至關重要的作用,因為C語言能和彙編指令幾乎能直接翻譯,而機器語言和彙編又能直接翻譯。所以在寫C語言的時候,程式碼的效率幾乎是用機器語言的效率。不過具體還要取決於具體的編譯器,不同的編譯器對程式碼

C語言字串常用處理技巧總結

1.從一串字串中提取中間一段,並單獨拿出來 char *pStart = NULL,*pMid = NULL,*pEnd = NULL,*t = NULL; pStart= strstr(pStart, "A"); pEnd = strstr(pStart, "

微控制器C語言程式碼_經驗技巧

1、如果可以的話少用庫函式,便於不同的mcu和編譯器間的移植   2、選擇合適的演算法和資料結構   應該熟悉演算法語言,知道各種演算法的優缺點,具體資料請參見相應的參考資料,有很多計算機書籍上都有介紹。將比較慢的順序查詢法用較快的二分查詢或亂序查詢法代替,插入排

高效記憶體池的設計方案[C語言]

作者:鄒祁峰 郵箱:[email protected] 日期:2012.11.18 凌晨02:00 轉載請註明來自"祁峰"的CSDN部落格 1 引言     本人在轉發的博文《記憶體池的

C語言全域性變數定義與宣告技巧

在實際的程式設計中,全域性變數對我們程式設計來說既是喜又是淚,雖然說專案中儘量避免使用全域性變數,但總有些時候不得不使用它,並且可能使用得不少,各個模組可能有含有或多或少的幾個全域性變數,而當別的模組需要引用的時候,就必須extern它,造成你定義了一遍又聲明瞭一遍,這樣就

C語言中一些很酷的技巧(cool tricks)

1.  #if 0 ...... #endif 塊中的內容不會被編譯,因為註釋不允許巢狀,我們可以把暫時不用的程式碼塊放在 這裡面。 2. 陣列初始化的時候可以指定索引,而且可以給特定範圍的陣列賦值。 比如  int array[] = { [0 ... 9] = 1, [10 ... 20] = 2, [

c語言技巧

1、整數/整數=整數 浮點數/浮點數=浮點數 2、數學函式(#include<math.h>)sqrt可以用來計算整數和浮點數的算術平方根 3、pi的規範寫法pi=const doule pi=acos(-1);(#include<math.h>)儘