中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
超炫酷技巧!C語言代碼優(yōu)化的技巧

直接來源:嵌入式大雜燴

一、變量與值得比較

1、布爾變量與零值的比較

不可將布爾變量直接與 TRUE、 FALSE或者 1、 0進行比較 。據(jù)布爾類型的語義,零值為“ 假”(記為 FALSE),任何非零值都是“ 真”(記為TRUE)。

TRUE的值究竟是什么并沒有統(tǒng)一的標準。例如 Visual C++ 將 TRUE定義為 1, 而 Visual Basic則將 TRUE定義為-1 。

假設布爾變量名字為 flag,它與零值比較的標準 if語句如下:

if (flag) // 表示flag為真
if (!flag) // 表示flag為假

其它的用法都屬于不良風格,例如:

if (flag == TRUE)
if (flag == 1 )
if (flag == FALSE)
if (flag == 0)

2、整形變量與零值的比較

應當將整型變量用“ ==” 或“ !=” 直接與 0比較 。假設整型變量的名字為 value,它與零值比較的標準 if語句如下:

if (value == 0)
if (value != 0)

不可模仿布爾變量的風格而寫成:

if (value) // 會讓人誤解 value是布爾變量
if (!value)

3、浮點變量與零值的比較

不可將浮點變量用“ ==” 或“ !=” 與任何數(shù)字比較 。千萬要留意, 無論是 float還是 double類型的變量, 都有精度限制。

所以一定要避免將浮點變量用“ ==” 或“ !=” 與數(shù)字比較,應該設法轉化成“ >=” 或“ <=” 形式。假設浮點變量的名字為 x,應當 將:

if (x == 0.0) // 隱含錯誤的比

轉化為:

if ((x>=-EPSINON) && (x<=EPSINON))

其中 EPSINON是允許的誤差(即精度) 。

4、指針變量與零值的比較

應當將指針變量用“ ==” 或“ !=” 與 NULL比較 。指針變量的零值是“ 空”(記為 NULL)。

盡管 NULL 的值與 0相同,但是兩者意義不同。假設指針變量的名字為 p,它與零值比較的標準 if語句如下:

if (p == NULL) // p與 NULL顯式比較,強調 p是指針變量
if (p != NULL)

不要寫成:

if (p == 0) // 容易讓人誤解 p是整型變量
if (p != 0)

或者:

if (p) // 容易讓人誤解p是布爾變量
if (!p)

二、變量及基本運算

1、整型數(shù)

如果我們確定整數(shù)非負,就應該使用unsigned int而不是int。

有些處理器處理無符號unsigned 整形數(shù)的效率遠遠高于有符號signed整形數(shù)(這是一種很好的做法,也有利于代碼具體類型的自解釋)。

因此,在一個緊密循環(huán)中,聲明一個int整形變量的最好方法是:

registerunsignedint variable_name;

記住,整形in的運算速度高浮點型float,并且可以被處理器直接完成運算,而不需要借助于FPU(浮點運算單元)或者浮點型運算庫。

盡管這不保證編譯器一定會使用到寄存器存儲變量,也不能保證處理器處理能更高效處理unsigned整型,但這對于所有的編譯器是通用的。

例如在一個計算包中,如果需要結果精確到小數(shù)點后兩位,我們可以將其乘以100,然后盡可能晚的把它轉換為浮點型數(shù)字。

2、除法和取余數(shù)

在標準處理器中,對于分子和分母,一個32位的除法需要使用20至140次循環(huán)操作。

除法函數(shù)消耗的時間包括一個常量時間加上每一位除法消耗的時間。

Time (numerator / denominator) = C0 + C1* log2 (numerator / denominator)
= C0 + C1 * (log2 (numerator) - log2 (denominator)).

對于ARM處理器,這個版本需要20+4.3N次循環(huán)。這是一個消耗很大的操作,應該盡可能的避免執(zhí)行。

有時,可以通過乘法表達式來替代除法。例如,假如我們知道b是正數(shù)并且b*c是個整數(shù),那么(a/b)>c可以改寫為a>(c*b)。

如果確定操作數(shù)是無符號unsigned的,使用無符號unsigned除法更好一些,因為它比有符號signed除法效率高。

3、取模的一種替代方法

我們使用取余數(shù)操作符來提供算數(shù)取模。但有時可以結合使用if語句進行取模操作??紤]如下兩個例子:

uint modulo_func1 (uint count)
{
return (++count % 60);
}

uint modulo_func2 (uint count)
{
if (++count >= 60)
count = 0;
return (count);
}

優(yōu)先使用if語句,而不是取余數(shù)運算符,因為if語句的執(zhí)行速度更快。這里注意新版本函數(shù)只有在我們知道輸入的count結余0至59時在能正確的工作。

4、使用數(shù)組下標

如果你想給一個變量設置一個代表某種意思的字符值,你可能會這樣做:

switch ( queue )
{
case0 : letter = 'W';
break;
case1 : letter = 'S';
break;
case2 : letter = 'U';
break;
}

或者這樣做:

if ( queue == 0 )
letter = 'W';
elseif ( queue == 1 )
letter = 'S';
else
letter = 'U';

一種更簡潔、更快的方法是使用數(shù)組下標獲取字符數(shù)組的值。如下:

staticchar *classes='WSU';
letter = classes[queue];

5、使用別名

考慮如下的例子:

void func1( int *data )
{
int i;

for(i=0; i<10; i++)
{
anyfunc( *data, i);
}
}

盡管*data的值可能從未被改變,但編譯器并不知道anyfunc函數(shù)不會修改它,所以程序必須在每次使用它的時候從內存中讀取它。如果我們知道變量的值不會被改變,那么就應該使用如下的編碼:

void func1( int *data )
{
int i;
int localdata;

localdata = *data;
for(i=0; i<10; i++)
{
anyfunc ( localdata, i);
}
}

這為編譯器優(yōu)化代碼提供了條件。

6、局部變量的類型

我們應該盡可能的不使用char和short類型的局部變量。對于char和short類型,編譯器需要在每次賦值的時候將局部變量減少到8或者16位。

這對于有符號變量稱之為有符號擴展,對于無符號變量稱之為零擴展。這些擴展可以通過寄存器左移24或者16位,然后根據(jù)有無符號標志右移相同的位數(shù)實現(xiàn),這會消耗兩次計算機指令操作(無符號char類型的零擴展僅需要消耗一次計算機指令)。

可以通過使用int和unsigned int類型的局部變量來避免這樣的移位操作。這對于先加載數(shù)據(jù)到局部變量,然后處理局部變量數(shù)據(jù)值這樣的操作非常重要。無論輸入輸出數(shù)據(jù)是8位或者16位,將它們考慮為32位是值得的。

考慮下面的三個函數(shù):

int wordinc (int a)
{
return a + 1;
}
short shortinc (short a)
{
return a + 1;
}
char charinc (char a)
{
return a + 1;
}

盡管結果均相同,但是第一個程序片段運行速度高于后兩者。

三、循環(huán)語句

1、多重循環(huán)

在多重循環(huán)中, 如果有可能, 應當將最長的循環(huán)放在最內層, 最短的循環(huán)放在最外層,以減少 CPU 跨切循環(huán)層的次數(shù)。例如示例 4-4(b)的效率比示例4-4(a)的高 :

2、循環(huán)體內的判斷

如果循環(huán)體內存在邏輯判斷, 并且循環(huán)次數(shù)很大, 宜將邏輯判斷移到循環(huán)體的外面。

示例 4-4(c)的程序比示例 4-4(d)多執(zhí)行了 N-1次邏輯判斷。并且由于前者老要進行邏輯判斷,打斷了循環(huán)“ 流水線” 作業(yè),使得編譯器不能對循環(huán)進行優(yōu)化處理, 降低了效率。

如果N非常大, 最好采用示例 4-4(d)的寫法, 可以提高效率。如果 N非常小,兩者效率差別并不明顯,采用示例 4-4(c)的寫法比較好, 因為程序更加簡潔。

3、for 語句的循環(huán)控制變量

不可在 for 循環(huán)體內修改循環(huán)變量,防止 for 循環(huán)失去控制 。建議 for語句的循環(huán)控制變量的取值采用“ 半開半閉區(qū)間” 寫法。

示例 4-5(a)中的 x值屬于半開半閉區(qū)間“ 0 =< x < N”,起點到終點的間隔為 N,循環(huán)次數(shù)為 N。

示例 4-5(b)中的 x值屬于閉區(qū)間“ 0 =< x <= N-1”,起點到終點的間隔為 N-1,循環(huán)次數(shù)為 N。

相比之下,示例 4-5(a)的寫法更加直觀,盡管兩者的功能是相同的 。

4、更快的for()循環(huán)

這是一個簡單而高效的概念。通常,我們編寫for循環(huán)代碼如下:

for( i=0; i<10; i++){ ... }

i從0循環(huán)到9。如果我們不介意循環(huán)計數(shù)的順序,我們可以這樣寫:

for( i=10; i--; ) { ... }

這樣快的原因是因為它能更快的處理i的值–測試條件是:i是非零的嗎?如果這樣,遞減i的值。對于上面的代碼,處理器需要計算“計算i減去10,其值非負嗎?

如果非負,i遞增并繼續(xù)”。簡單的循環(huán)卻有很大的不同。這樣,i從9遞減到0,這樣的循環(huán)執(zhí)行速度更快。

這里的語法有點奇怪,但確實合法的。循環(huán)中的第三條語句是可選的(無限循環(huán)可以寫為for(;;))。如下代碼擁有同樣的效果:

for(i=10; i; i--){}

或者更進一步的:

for(i=10; i!=0; i--){}

這里我們需要記住的是循環(huán)必須終止于0(因此,如果在50到80之間循環(huán),這不會起作用),并且循環(huán)計數(shù)器是遞減的。使用遞增循環(huán)計數(shù)器的代碼不享有這種優(yōu)化。

四、指針

我們應該盡可能的使用引用值的方式傳遞結構數(shù)據(jù),也就是說使用指針,否則傳遞的數(shù)據(jù)會被拷貝到棧中,從而降低程序的性能。

函數(shù)通過參數(shù)接受結構數(shù)據(jù)的指針,如果我們確定不改變數(shù)據(jù)的值,我們需要將指針指向的內容定義為常量。例如:

void print_data_of_a_structure ( const Thestruct *data_pointer)
{
...printf contents of the structure...
}

這個示例告訴編譯器函數(shù)不會改變外部參數(shù)的值(使用const修飾),并且不用在每次訪問時都進行讀取。

同時,確保編譯器限制任何對只讀結構的修改操作從而給予結構數(shù)據(jù)額外的保護。

五、懶檢測開發(fā)

if(a>10 && b=4)這樣的語句中,確保AND表達式的第一部分最可能較快的給出結果(或者最早、最快計算),這樣第二部分便有可能不需要執(zhí)行。

六、用switch()函數(shù)替代if…else…

對于涉及if…else…else…這樣的多條件判斷,例如:

if( val == 1)
dostuff1();
elseif (val == 2)
dostuff2();
elseif (val == 3)
dostuff3();

使用switch可能更快:

switch( val )
{
case1: dostuff1(); break;

case2: dostuff2(); break;

case3: dostuff3(); break;
}

在if()語句中,如果最后一條語句命中,之前的條件都需要被測試執(zhí)行一次。switch允許我們不做額外的測試。如果必須使用if…else…語句,將最可能執(zhí)行的放在最前面。

函數(shù)相關

1、參數(shù)的書寫要完整

參數(shù)的書寫要完整,不要貪圖省事只寫參數(shù)的類型而省略參數(shù)名字。如果函數(shù)沒有參數(shù),則用void填充。例如:

voidSetValue(intwidth,intheight); // 良好的風格
voidSetValue(int,int); // 不良的風格
floatGetValue(void); // 良好的風格
floatGetValue(); // 不良的風格

2、參數(shù)命名要恰當,順序要合理

例如編寫字符串拷貝函數(shù)StringCopy,它有兩個參數(shù)。如果把參數(shù)名字起為str1和str2,例如:

void StringCopy(char*str1,char*str2);

那么我們很難搞清楚究竟是把str1拷貝到str2中,還是剛好倒過來。

可以把參數(shù)名字起得更有意義,如叫strSourcestrDestination。這樣從名字上就可以看出應該把strSource拷貝到strDestination。

還有一個問題,這兩個參數(shù)那一個該在前那一個該在后?參數(shù)的順序要遵循程序員的習慣。一般地,應將目的參數(shù)放在前面,源參數(shù)放在后面:

void StringCopy(char*strDestination,char*strSource);

3、參數(shù)是指針

如果參數(shù)是指針,且僅作輸入用,則應在類型前加const,以防止該指針在函數(shù)體內被意外修改。

例如:

void StringCopy(char*strDestination,constchar*strSource);

4、不要省略返回值的類型

C語言中,凡不加類型說明的函數(shù),一律自動按整型處理。這樣做不會有什么好處,卻容易被誤解為void類型。

5、函數(shù)名字與返回值類型在語義上不可沖突

違反這條規(guī)則的典型代表是C標準庫函數(shù)getchar。例如:

charc;
c=getchar();
if(c==EOF)

按照getchar名字的意思,將變量c聲明為char類型是很自然的事情。但不幸的是getchar的確不是char類型,而是int類型,其原型如下:

int getchar(void);

由于c是char類型,取值范圍是[-128,127],如果宏EOF的值在char的取值范圍之外,那么if語句將總是失敗,這種“危險”人們一般哪里料得到!導致本例錯誤的責任并不在用戶,是函數(shù)getchar誤導了使用者。

6、不要將正常值和錯誤標志混在一起返回

正常值用輸出參數(shù)獲得,而錯誤標志用return語句返回。

回顧上例,C標準庫函數(shù)的設計者為什么要將getchar聲明為令人迷糊的int類型呢?

在正常情況下,getchar的確返回單個字符。但如果getchar碰到文件結束標志或發(fā)生讀錯誤,它必須返回一個標志EOF。為了區(qū)別于正常的字符,只好將EOF定義為負數(shù)(通常為負1)。因此函數(shù)getchar就成了int類型。

我們在實際工作中,經常會碰到上述令人為難的問題。為了避免出現(xiàn)誤解,我們應該將正常值和錯誤標志分開。即:正常值用輸出參數(shù)獲得,而錯誤標志用return語句返回。

函數(shù)getchar可以改寫成BOOL GetChar(char*c);。

7、附加返回值,增強函數(shù)的靈活性

有時候函數(shù)原本不需要返回值,但為了增加靈活性如支持鏈式表達,可以附加返回值。例如字符串拷貝函數(shù)strcpy的原型:

char *strcpy(char *strDest,const char *strSrc);

strcpy函數(shù)將strSrc拷貝至輸出參數(shù)strDest中,同時函數(shù)的返回值又是strDest。這樣做并非多此一舉,可以獲得如下靈活性:

char str[20];
int length=strlen(strcpy(str,“HelloWorld”));

循環(huán)展開

簡單的循環(huán)可以展開以獲取更好的性能,但需要付出代碼體積增加的代價。循環(huán)展開后,循環(huán)計數(shù)應該越來越小從而執(zhí)行更少的代碼分支。

如果循環(huán)迭代次數(shù)只有幾次,那么可以完全展開循環(huán),以便消除循壞帶來的負擔。例如:

for(i=0; i<3; i++)
{
    something(i);
}

展開為:

something(0);
something(1);
something(2);

這可以非常可觀的節(jié)省性能,原因是代碼不用每次循環(huán)需要檢查和增加i的值。

if判斷條件的順序

if的判斷條件中概率最大的情況應放在前面。例子:

if (1 == condition)
{

}
else if (2 == condition)
{

}
else
{

}

此處,若condition為1的概率大較大則把if (1 == condition)放在前面。

condition為2概率大較大則把if (2 == condition)放在前面,如:

if (2 == condition)
{

}
else if (1 == condition)
{

}
else
{

}

這里有個小細節(jié):在用if判斷某個變量與某個常量是否相等時,可以把常量寫在前面變量寫在后面,如:

if (2 == condition)

2放在前面,condition放在后面。這樣的好處就是當你漏敲了一個=號時,編譯器會指出你的這個錯誤。

盡早退出循環(huán)

通常,循環(huán)并不需要全部都執(zhí)行。例如,如果我們在從數(shù)組中查找一個特殊的值,一經找到,我們應該盡可能早的斷開循環(huán)。

例如:如下循環(huán)從10000個整數(shù)中查找是否存在-99。

found = FALSE;
for(i=0;i<10000;i++)
{
    iflist[i] == -99 )
    {
        found = TRUE;
    }
}

if( found ) 
{
    printf('Yes, there is a -99. Hooray!\n');
}

這段代碼無論我們是否查找得到,循環(huán)都會全部執(zhí)行完。更好的方法是一旦找到我們查找的數(shù)字就終止繼續(xù)查詢。

把程序修改為:

found = FALSE;
for(i=0;i<10000;i++)
{
    iflist[i] == -99 )
    {
        found = TRUE;
        break;
    }
}

if( found ) 
{
    printf('Yes, there is a -99. Hooray!\n');
}

假如待查數(shù)據(jù)位于第23個位置上,程序便會執(zhí)行23次,從而節(jié)省9977次循環(huán)。

使用位運算替代四則運算

在許多古老的微處理器上, 位運算比加減運算略快, 通常位運算比乘除法運算要快很多。

在現(xiàn)代架構中, 位運算的運算速度通常與加法運算相同,但仍然快于乘法運算。所以通常乘以或除以2n可以使用位運算來代替四則運算,如

a = a * 8;
a = a / 8;
a = a % 8;

修改為:

a = a << 3;
a = a >> 3;
a = a & 7;

以空間換時間

在內存比較充足的情況下,可以使用空間來換取時間。比如使用查表法,把一些可能的結果事先保存到表中。例如求階乘通常的做法是:

long factorial(int i)
{
    if (i == 0)
        return 1;
    else
        return i * factorial(i - 1);
}

若是空間比較足,而且所需的結果都能列舉出來,則代碼可以修改為:

static long factorial_table[] = {1, 1, 2, 6, 24, 120, 720  /* etc */ };
long factorial(int i)
{
    return factorial_table[i];
}

使用復合賦值語句

增加一個變量的值有兩種方式,如:a = a + 5a += 5。存在兩種增加一個變量值的方法有何意義呢?

K&R C設計者認為復合賦值符可以讓程序員把代碼寫得更清楚些。另外,編譯器可以產生更為緊湊的代碼。

現(xiàn)在,a = a + 5和a += 5之間的差別不再那么顯著,而且現(xiàn)代的編譯器為這兩種表達式產生優(yōu)化代碼并無多大問題。

但是,要考慮類似如下的語句:

a[2*(y-6*f(x))] = a[2*(y-6*f(x))] + 5;
a[2*(y-6*f(x))] += 5;

此處a為數(shù)組。在第一種形式種,由于編譯器無從知道f函數(shù)是否具有副作用,所以它必須兩次計算數(shù)組a的下標表達式的值。

而在第二種形式中,下標表達式只需計算一次,所以第二種形式效率更高。并且,從書寫的角度看,第一種形式的下標表達式需要書寫兩次,而第二種形式只需書寫一次。

盡量使循環(huán)體內的工作量達到最小化

循環(huán)中,隨著循環(huán)次數(shù)的增加,會加大對系統(tǒng)資源的消耗。我們應當確認一些操作是否必須放在循環(huán)體內。示例代碼:

for (i = 0; i < n; i++)
{
    tmp += i;
    sum = tmp;
}

這是個求和操作,但是這里每循環(huán)一次,就要進行一次sum = tmp;操作,這樣的寫法很浪費資源。這一條語句完全可以移至循環(huán)體外:

for (i = 0; i < n; i++)
{
    tmp += i;
}
sum = tmp;

這樣,sum = tmp;語句只執(zhí)行一次,不僅可以調高程序效率,也提高了可讀性。同時,我們還可以考慮類似這樣的代碼是否有必要封裝成一個函數(shù)供多個地方調用。

無限循環(huán)優(yōu)先選用for(;;),而不是while(1)

在C語言中,最常用的無限循環(huán)語句主要有兩種:while(1)for(;;)。從功能上講, 這兩種語句的效果完全一樣。那么,我們究竟該選擇哪一種呢?

其實,for(;;)語句運行速度要快一些。按照for的 語法規(guī)則,兩個分號分開的是3個表達式?,F(xiàn)在表達式為空,很自然地被編譯成無條件的跳轉(即無條件循環(huán),不用判斷條件)。如代碼for(;;)Microsoft Visual Studio 2010 集成開發(fā)環(huán)境VC++的Debug模式下將生成如下匯編代碼:

for(;;)
00931451 jmp main+41h (931451h)

相比之下,while語句就不一樣了。按照while的語法規(guī)則,while()語句中必須有一個 表達式(這里是1 )判斷條件,生成的代碼用它進行條件跳轉。即while語句()屬于有條件循環(huán),有條件就要判斷條件是否成立,所以其相對于for(;;)語句需要多幾條指令。如代碼 while (1)Microsoft Visual Studio 2010集成開發(fā)環(huán)境VC++的Debug模式下將生成如下匯 編代碼:

while(1)
011A1451 mov   eax,1
011A1456 test  eax,eax
011A1458 je    main+55h (11A1465h)
011A1463 jmp   main+41h (11A1451h)

根據(jù)上面的分析結果,很顯然,for(;;)語句指令少,不占用寄存器,而且沒有判斷、 跳轉指令。當然,如果從實際的編譯結果來看,兩者的效果常常是一樣的,因為大部分編譯 器都會對while (1)語句做一定的優(yōu)化。

但是,這還需要取決于編譯器。因此,我們還是應該優(yōu)先選用for(;;)語句。

沒有參數(shù)的函數(shù)必須用void填充

在C語言中,void的作用主要有兩個:

1、對函數(shù)返回值的限定。
2、對函數(shù)參數(shù)的限定。

看一個示例函數(shù):

int f()
{
    return 100;
}

從表面看,函數(shù)f()沒有參數(shù),也就是說,它不允許接受參數(shù)。但事實并非如此,我們來驗證一下:

#include <stdio.h>
int f()
{
    return 100;
}

int main(void)
{
    printf('%d\n', f(666));
    return 0;
}

編譯、運行結果為:

可見,使用GCC可正常通過編譯,這說明可以向無參數(shù)的函數(shù)傳遞參數(shù)。但是,需要注意的是,在一些IDE中不能通過編譯。

所以,為了提高程序的統(tǒng)一性、安全性與可讀性。我們對沒有參數(shù)的函數(shù)必須使用void進行填充。我們使用void填充上面的f函數(shù)之后,編譯就不通過了,報錯如下:

盡可能為簡單功能編寫函數(shù)

有時候,我們需要用函數(shù)去封裝僅用一兩行代碼就可完成的功能。對于這樣的函數(shù),單 從代碼最上看,好像沒有什么封裝的必要。但是,用函數(shù)可使其功能明確化、具體化,從而增加程序可讀性,并且也方便代碼的維護與測試。示例代碼如下:

int Max(int x,int y)
{
    return (x>y? x : y);
}
int Min(int x,int y)
{
    return (x<y?x:y);
}

當然,也可以使用宏來代替上面的函數(shù),代碼如下:

#define MAX(x,y)  (((x) > (y)) ? (x) : (y))
#define MIN(x,y)  (((x) < (y)) ? (x) : (y))

在C程序中,我們可以適當?shù)赜煤甏a來提高執(zhí)行效率。宏代碼本身不是函數(shù),但使用起來與函數(shù)相似。預處理器用復制宏代碼的方式代替函數(shù)調用,省去了參數(shù)壓棧、生成匯編語言的CALL調用、返回參數(shù)、執(zhí)行return等過程,從而提高了運行速度。但是,使用宏代碼最大的缺點就是容易出錯,預處理器在復制宏代碼時常常產生意想不到的邊際效應。關于帶參宏的筆記:【C語言筆記】學習使用帶參宏(一)、【C語言筆記】學習使用帶參宏(二)

因此, 盡管看起來宏要比函數(shù)簡單得多,但還是建議使用函數(shù)的形式來封裝這些簡單功能的代碼。

函數(shù)地抽象級別應在同一個層次

先來看下面一段示例代碼:

void Init(void)
{
    /* 本地初始化 */
    ......
    /* 遠程初始化 */
    InitRemote();
}

void InitRemote(void)
{
    /* 遠程初始化 */
    ......
}

上面地Init函數(shù)主要完成本地初始化與遠程初始化工作,在其功能上沒有什么不妥之處。但從設計觀點看,卻存在這一定缺陷。因為本地初始化與遠程初始化層次相當,本地初始化也應當作為獨立的函數(shù)存在。應改為:

void Init(void)
{
    /* 本地初始化 */
    InitLocal();
    /* 遠程初始化 */
    InitRemote();
}

void InitLocal(void)
{
    /* 本地初始化 */
    ......
}

void InitRemote(void)
{
    /* 遠程初始化 */
    ......
}

盡量避免在非調度函數(shù)中使用控制參數(shù)

在函數(shù)設計中,我們可以將函數(shù)簡單地分為兩大類:調度函數(shù)與非調度函數(shù)(非調度函數(shù)一般也稱為功能函數(shù)或實現(xiàn)函數(shù))。

所謂的調度函數(shù)是指根據(jù)輸入的消息類型或控制命令來啟動相應的功能實體(即函數(shù)或過程)的函數(shù)。調度函數(shù)本身不能提供功能實現(xiàn),相反,它必須委托給實現(xiàn)函數(shù)來完成具體的功能。也就是說,調度型函數(shù)永遠只關注“what to do”,而“how to do”則是由實現(xiàn)函數(shù)來關心的,調度函數(shù)不需要關心“how to do”。這種調度函數(shù)與實現(xiàn)函數(shù)的分離設計也滿足了單一職責的原則,即調度的不實現(xiàn),實現(xiàn)的不調度。

對調度函數(shù)來講,控制參數(shù)是指改變函數(shù)功能行為的參數(shù),即函數(shù)要根據(jù)此參數(shù)來決定具體怎樣工作。然而,如果在非調度函數(shù)中也使用控制參數(shù)來決定具體怎樣工作,那么這樣做無疑會增加函數(shù)間的控制耦合,很可能使函數(shù)間的耦合度增大,并使函數(shù)的功能不唯一, 違背了函數(shù)功能的單一原則。示例代碼如下:

int Calculateint a, int b, const int calculate_flag )
{
    int sum = 0;
    switch(calculate_flag)
    {
        case 1: 
            sum = a + b; 
            break;
        case 2
            sum = a - b;
        case 3: 
            sum = a * b; 
            break;
        case 4: 
            sum = a / b; 
            break;
        default: 
            printf('error\n');
            break;
    }
    return sum;
}

上面的函數(shù)雖然看起來很簡潔,實際上這種設計是不合理的。由于控制參數(shù)calculate_flag的原因,使函數(shù)間的耦合度增大,也違背了函數(shù)的功能單一原則。因此,不如分為如下4個函數(shù)清晰,示例代碼如下:

int Add(int a,int b)
{
    return a + b;
}
int Sub(int a,int b)
{
    return a - b;
}
int Mul(int a,int b)
{
    return a * b;
}
int Div(int a,int b)
{
    return a / b;
}
本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
程序代碼編寫規(guī)范
高質量C/C++編程(片段)
為什么Linux內核里大量使用goto,而很多書籍卻不提倡使用?
c++之指針作為函數(shù)參數(shù)傳遞的問題
對于這些C語言基礎知識你知道哪些?快來看看吧
C/C :基本語法看這一篇就夠了
更多類似文章 >>
生活服務
熱點新聞
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服