直接來源:嵌入式大雜燴
一、變量與值得比較
不可將布爾變量直接與 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)
應當將整型變量用“ ==” 或“ !=” 直接與 0比較 。假設整型變量的名字為 value,它與零值比較的標準 if語句如下:
if (value == 0)
if (value != 0)
不可模仿布爾變量的風格而寫成:
if (value) // 會讓人誤解 value是布爾變量
if (!value)
不可將浮點變量用“ ==” 或“ !=” 與任何數(shù)字比較 。千萬要留意, 無論是 float還是 double類型的變量, 都有精度限制。
所以一定要避免將浮點變量用“ ==” 或“ !=” 與數(shù)字比較,應該設法轉化成“ >=” 或“ <=” 形式。假設浮點變量的名字為 x,應當 將:
if (x == 0.0) // 隱含錯誤的比
轉化為:
if ((x>=-EPSINON) && (x<=EPSINON))
其中 EPSINON是允許的誤差(即精度) 。
應當將指針變量用“ ==” 或“ !=” 與 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)
如果我們確定整數(shù)非負,就應該使用unsigned int而不是int。
有些處理器處理無符號unsigned 整形數(shù)的效率遠遠高于有符號signed整形數(shù)(這是一種很好的做法,也有利于代碼具體類型的自解釋)。
因此,在一個緊密循環(huán)中,聲明一個int整形變量的最好方法是:
registerunsignedint variable_name;
記住,整形in的運算速度高浮點型float,并且可以被處理器直接完成運算,而不需要借助于FPU(浮點運算單元)或者浮點型運算庫。
盡管這不保證編譯器一定會使用到寄存器存儲變量,也不能保證處理器處理能更高效處理unsigned整型,但這對于所有的編譯器是通用的。
例如在一個計算包中,如果需要結果精確到小數(shù)點后兩位,我們可以將其乘以100,然后盡可能晚的把它轉換為浮點型數(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除法效率高。
我們使用取余數(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時在能正確的工作。
如果你想給一個變量設置一個代表某種意思的字符值,你可能會這樣做:
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];
考慮如下的例子:
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)化代碼提供了條件。
我們應該盡可能的不使用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)中, 如果有可能, 應當將最長的循環(huán)放在最內層, 最短的循環(huán)放在最外層,以減少 CPU 跨切循環(huán)層的次數(shù)。例如示例 4-4(b)的效率比示例4-4(a)的高 :
如果循環(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)的寫法比較好, 因為程序更加簡潔。
不可在 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)的寫法更加直觀,盡管兩者的功能是相同的 。
這是一個簡單而高效的概念。通常,我們編寫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ù)額外的保護。
在if(a>10 && b=4)
這樣的語句中,確保AND表達式的第一部分最可能較快的給出結果(或者最早、最快計算),這樣第二部分便有可能不需要執(zhí)行。
對于涉及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ù)的書寫要完整,不要貪圖省事只寫參數(shù)的類型而省略參數(shù)名字。如果函數(shù)沒有參數(shù),則用void填充。例如:
voidSetValue(intwidth,intheight); // 良好的風格
voidSetValue(int,int); // 不良的風格
floatGetValue(void); // 良好的風格
floatGetValue(); // 不良的風格
例如編寫字符串拷貝函數(shù)StringCopy,它有兩個參數(shù)。如果把參數(shù)名字起為str1和str2,例如:
void StringCopy(char*str1,char*str2);
那么我們很難搞清楚究竟是把str1拷貝到str2中,還是剛好倒過來。
可以把參數(shù)名字起得更有意義,如叫strSource
和strDestination
。這樣從名字上就可以看出應該把strSource拷貝到strDestination。
還有一個問題,這兩個參數(shù)那一個該在前那一個該在后?參數(shù)的順序要遵循程序員的習慣。一般地,應將目的參數(shù)放在前面,源參數(shù)放在后面:
void StringCopy(char*strDestination,char*strSource);
如果參數(shù)是指針,且僅作輸入用,則應在類型前加const,以防止該指針在函數(shù)體內被意外修改。
例如:
void StringCopy(char*strDestination,constchar*strSource);
C語言中,凡不加類型說明的函數(shù),一律自動按整型處理。這樣做不會有什么好處,卻容易被誤解為void類型。
違反這條規(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
誤導了使用者。
正常值用輸出參數(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);
。
有時候函數(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)計數(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 (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)并不需要全部都執(zhí)行。例如,如果我們在從數(shù)組中查找一個特殊的值,一經找到,我們應該盡可能早的斷開循環(huán)。
例如:如下循環(huán)從10000個整數(shù)中查找是否存在-99。
found = FALSE;
for(i=0;i<10000;i++)
{
if( list[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++)
{
if( list[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 + 5
和a += 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)次數(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ù)供多個地方調用。
在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(;;)語句。
在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ù)可使其功能明確化、具體化,從而增加程序可讀性,并且也方便代碼的維護與測試。示例代碼如下:
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ù)的形式來封裝這些簡單功能的代碼。
先來看下面一段示例代碼:
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ù)或實現(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 Calculate( int 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;
}
聯(lián)系客服