青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

旅途

如果想飛得高,就該把地平線忘掉

函數可重入性及編寫規范

一、可重入函數
1)什么是可重入性?
可重入(reentrant)函數可以由多于一個任務并發使用,而不必擔心數據錯誤。相反, 不可重入(non-reentrant)函數不能由超過一個任務所共享,除非能確保函數的互斥(或者使用信號量,或者在代碼的關鍵部分禁用中斷)。可重入 函數可以在任意時刻被中斷,稍后再繼續運行,不會丟失數據。可重入函數要么使用本地變量,要么在使用全局變量時保護自己的數據。

2)可重入函數:
不為連續的調用持有靜態數據。
不返回指向靜態數據的指針;所有數據都由函數的調用者提供。
使用本地數據,或者通過制作全局數據的本地拷貝來保護全局數據。
如果必須訪問全局變量,記住利用互斥信號量來保護全局變量。
絕不調用任何不可重入函數。

3)不可重入函數:
函數中使用了靜態變量,無論是全局靜態變量還是局部靜態變量。
函數返回靜態變量。
函數中調用了不可重入函數。
函數體內使用了靜態的數據結構;
函數體內調用了malloc()或者free()函數;
函數體內調用了其他標準I/O函數。
函數是singleton中的成員函數而且使用了不使用線程獨立存儲的成員變量 。
總的來說,如果一個函數在重入條件下使用了未受保護的共享的資源,那么它是不可重入的。

4)示例
在多線程條件下,函數應當是線程安全的,進一步,更強的條件是可重入的。可重入函數保證了在多線程條件下,函數的狀態不會出現錯誤。以下分別是一個不可重入和可重入函數的示例:
//c code
static int tmp;
void func1(int* x, int* y) {
    tmp=*x;
    *x=*y;
    *y=tmp;
}
void func2(int* x, int* y) {
    int tmp;
    tmp=*x;
    *x=*y;
    *y=tmp;
}
func1是不可重入的,func2是可重入的。因為在多線程條件下,操作系統會在func1還沒有執行完的情況下,切換到另一個線程中,那個線程可能再次調用func1,這樣狀態就錯了。

二、函數編寫規范
1 :對所調用函數的錯誤返回碼要仔細、全面地處理 
 
2 :明確函數功能,精確(而不是近似)地實現函數設計 
 
3 :編寫可重入函數時,應注意局部變量的使用(如編寫C/C++ 語言的可重入函數時,應使用auto 即缺省態局部變量或寄存器變量)
說明:編寫C/C++語言的可重入函數時,不應使用static局部變量,否則必須經過特殊處理,才能使函數具有可重入性。
 
4 :編寫可重入函數時,若使用全局變量,則應通過關中斷、信號量(即P 、V 操作)等手段對其加以保護
說明:若對所使用的全局變量不加以保護,則此函數就不具有可重入性,即當多個進程調用此函數時,很有可能使有關全局變量變為不可知狀態。
示例:假設Exam是int型全局變量,函數Squre_Exam返回Exam平方值。那么如下函數不具有可重入性。
unsigned int example( int para )
{
    unsigned int temp;
    Exam = para; // (**)
    temp = Square_Exam( );
    return temp;
}
此 函數若被多個進程調用的話,其結果可能是未知的,因為當(**)語句剛執行完后,另外一個使用本函數的進程可能正好被激活,那么當新激活的進程執行到此函 數時,將使Exam賦與另一個不同的para值,所以當控制重新回到“temp = Square_Exam( )”后,計算出的temp很可能不是預想中的結果。此函數應如下改進。
unsigned int example( int para )
{
    unsigned int temp;
    [申請信號量操作]        // 若申請不到“信號量”,說明另外的進程正處于
    Exam = para;            // 給Exam賦值并計算其平方過程中(即正在使用此
    temp = Square_Exam( );  // 信號),本進程必須等待其釋放信號后,才可繼
    [釋放信號量操作]        // 續執行。若申請到信號,則可繼續執行,但其
                            // 它進程必須等待本進程釋放信號量后,才能再使
                            // 用本信號。
    return temp;
}
 
5 :在同一項目組應明確規定對接口函數參數的合法性檢查應由函數的調用者負責還是由接口函數本身負責,缺省是由函數調用者負責
說 明:對于模塊間接口函數的參數的合法性檢查這一問題,往往有兩個極端現象,即:要么是調用者和被調用者對參數均不作合法性檢查,結果就遺漏了合法性檢查這 一必要的處理過程,造成問題隱患;要么就是調用者和被調用者均對參數進行合法性檢查,這種情況雖不會造成問題,但產生了冗余代碼,降低了效率。 
  
6 :防止將函數的參數作為工作變量
說明:將函數的參數作為工作變量,有可能錯誤地改變參數內容,所以很危險。對必須改變的參數,最好先用局部變量代之,最后再將該局部變量的內容賦給該參數。
示例:如下函數的實現就不太好。
void sum_data( unsigned int num, int *data, int *sum )
{
    unsigned int count;
    *sum = 0;
 
    for (count = 0; count < num; count++)
    {
        *sum  += data[count]; // sum成了工作變量,不太好。
    }
}
若改為如下,則更好些。
void sum_data( unsigned int num, int *data, int *sum )
{
    unsigned int count ;
    int sum_temp;
    sum_temp = 0;
 
    for (count = 0; count < num; count ++)
    {
        sum_temp  += data[count];
    }
 
    *sum = sum_temp;
}
  
7 :函數的規模盡量限制在200 行以內
說明:不包括注釋和空格行。 
8 :一個函數僅完成一件功能 

9 :為簡單功能編寫函數
說明:雖然為僅用一兩行就可完成的功能去編函數好象沒有必要,但用函數可使功能明確化,增加程序可讀性,亦可方便維護、測試。
示例:如下語句的功能不很明顯。
value = ( a > b ) ? a : b ;
改為如下就很清晰了。
 
int max (int a, int b)
{
    return ((a > b) ? a : b);
}
 
value = max (a, b);
 
或改為如下。
 
#define MAX (a, b) (((a) > (b)) ? (a) : (b))
 
value = MAX (a, b);
 
10:不要設計多用途面面俱到的函數
說明:多功能集于一身的函數,很可能使函數的理解、測試、維護等變得困難。 
 
11:函數的功能應該是可以預測的,也就是只要輸入數據相同就應產生同樣的輸出
說 明:帶有內部“存儲器”的函數的功能可能是不可預測的,因為它的輸出可能取決于內部存儲器(如某標記)的狀態。這樣的函數既不易于理解又不利于測試和維 護。在C/C++語言中,函數的static局部變量是函數的內部存儲器,有可能使函數的功能不可預測,然而,當某函數的返回值為指針類型時,則必須是 STATIC的局部變量的地址作為返回值,若為AUTO類,則返回為錯針。
示例:如下函數,其返回值(即功能)是不可預測的。
 
unsigned int integer_sum( unsigned int base )
{
    unsigned int index;
    static unsigned int sum = 0; // 注意,是static類型的。
                                 // 若改為auto類型,則函數即變為可預測。
    for (index = 1; index <= base; index++)
    {
        sum += index;
    }
    return sum;
}
  
12 :盡量不要編寫依賴于其他函數內部實現的函數
說明:此條為函數獨立性的基本要求。由于目前大部分高級語言都是結構化的,所以通過具體語言的語法要求與編譯器功能,基本就可以防止這種情況發生。但在匯編語言中,由于其靈活性,很可能使函數出現這種情況。
示例:如下是在DOS下TASM的匯編程序例子。過程Print_Msg的實現依賴于Input_Msg的具體實現,這種程序是非結構化的,難以維護、修改。
 
...  // 程序代碼
proc Print_Msg // 過程(函數)Print_Msg
    ...  // 程序代碼
    jmp  LABEL
    ...  // 程序代碼
endp
 
proc Input_Msg // 過程(函數)Input_Msg
    ...  // 程序代碼
LABEL:
    ...  // 程序代碼
endp

13 :避免設計多參數函數,不使用的參數從接口中去掉
說明:目的減少函數間接口的復雜度。 
  
14 :非調度函數應減少或防止控制參數,盡量只使用數據參數
說 明:本建議目的是防止函數間的控制耦合。調度函數是指根據輸入的消息類型或控制命令,來啟動相應的功能實體(即函數或過程),而本身并不完成具體功能。控 制參數是指改變函數功能行為的參數,即函數要根據此參數來決定具體怎樣工作。非調度函數的控制參數增加了函數間的控制耦合,很可能使函數間的耦合度增大, 并使函數的功能不唯一。
示例:如下函數構造不太合理。
int add_sub( int a, int b, unsigned char add_sub_flg )
{
    if (add_sub_flg == INTEGER_ADD)
    {
        return (a + b);
    }
    else
    {
        return (a  b);
    }
}
不如分為如下兩個函數清晰。
int add( int a, int b )
{
    return (a + b);
}
 
int sub( int a, int b )
{
    return (a  b);
}
15 :檢查函數所有參數輸入的有效性 
 
16 :檢查函數所有非參數輸入的有效性,如數據文件、公共變量等
說明:函數的輸入主要有兩種:一種是參數輸入;另一種是全局變量、數據文件的輸入,即非參數輸入。函數在使用輸入之前,應進行必要的檢查。 
  
17 :函數名應準確描述函數的功能 
  
18 :使用動賓詞組為執行某操作的函數命名。如果是OOP 方法,可以只有動詞(名詞是對象本身)
示例:參照如下方式命名函數。
void print_record( unsigned int rec_ind ) ;
int  input_record( void ) ;
unsigned char get_current_color( void ) ;
  
19 :避免使用無意義或含義不清的動詞為函數命名
說明:避免用含義不清的動詞如process、handle等為函數命名,因為這些動詞并沒有說明要具體做什么。
  
20 :函數的返回值要清楚、明了,讓使用者不容易忽視錯誤情況
說明:函數的每種出錯返回值的意義要清晰、明了、準確,防止使用者誤用、理解錯誤或忽視錯誤返回碼。 
  
21 :除非必要,最好不要把與函數返回值類型不同的變量,以編譯系統默認的轉換方式或強制的轉換方式作為返回值返回 
  
22 :讓函數在調用點顯得易懂、容易理解 
  
23 :在調用函數填寫參數時,應盡量減少沒有必要的默認數據類型轉換或強制數據類型轉換
說明:因為數據類型轉換或多或少存在危險。 
  
24 :避免函數中不必要語句,防止程序中的垃圾代碼
說明:程序中的垃圾代碼不僅占用額外的空間,而且還常常影響程序的功能與性能,很可能給程序的測試、維護等造成不必要的麻煩。 
  
25 :防止把沒有關聯的語句放到一個函數中
說 明:防止函數或過程內出現隨機內聚。隨機內聚是指將沒有關聯或關聯很弱的語句放到同一個函數或過程中。隨機內聚給函數或過程的維護、測試及以后的升級等造 成了不便,同時也使函數或過程的功能不明確。使用隨機內聚函數,常常容易出現在一種應用場合需要改進此函數,而另一種應用場合又不允許這種改進,從而陷入 困境。
在編程時,經常遇到在不同函數中使用相同的代碼,許多開發人員都愿把這些代碼提出來,并構成一個新函數。若這些代碼關聯較大并且是完成一個功能的,那么這種構造是合理的,否則這種構造將產生隨機內聚的函數。
示例:如下函數就是一種隨機內聚。
 
void Init_Var( void )
{
    Rect.length = 0;
    Rect.width = 0; /* 初始化矩形的長與寬 */
    Point.x = 10;
    Point.y = 10;   /* 初始化“點”的坐標 */
}
 
矩形的長、寬與點的坐標基本沒有任何關系,故以上函數是隨機內聚。
應如下分為兩個函數:
void Init_Rect( void )
{
    Rect.length = 0;
    Rect.width = 0; /* 初始化矩形的長與寬 */
}
 
void Init_Point( void )
{
    Point.x = 10;
    Point.y = 10;   /* 初始化“點”的坐標 */
}
 
26:如果多段代碼重復做同一件事情,那么在函數的劃分上可能存在問題
說明:若此段代碼各語句之間有實質性關聯并且是完成同一件功能的,那么可考慮把此段代碼構造成一個新的函數。 
 
27:功能不明確較小的函數,特別是僅有一個上級函數調用它時,應考慮把它合并到上級函數中,而不必單獨存在
說明:模塊中函數劃分的過多,一般會使函數間的接口變得復雜。所以過小的函數,特別是扇入很低的或功能不明確的函數,不值得單獨存在。 
  
28 :設計高扇入、合理扇出(小于7 )的函數
說明:扇出是指一個函數直接調用(控制)其它函數的數目,而扇入是指有多少上級函數調用它。
扇 出過大,表明函數過分復雜,需要控制和協調過多的下級函數;而扇出過小,如總是1,表明函數的調用層次可能過多,這樣不利程序閱讀和函數結構的分析,并且 程序運行時會對系統資源如堆棧空間等造成壓力。函數較合理的扇出(調度函數除外)通常是3-5。扇出太大,一般是由于缺乏中間層次,可適當增加中間層次的 函數。扇出太小,可把下級函數進一步分解多個函數,或合并到上級函數中。當然分解或合并函數時,不能改變要實現的功能,也不能違背函數間的獨立性。
扇入越大,表明使用此函數的上級函數越多,這樣的函數使用效率高,但不能違背函數間的獨立性而單純地追求高扇入。公共模塊中的函數及底層函數應該有較高的扇入。
較良好的軟件結構通常是頂層函數的扇出較高,中層函數的扇出較少,而底層函數則扇入到公共模塊中。 
  
29 :減少函數本身或函數間的遞歸調用
說明:遞歸調用特別是函數間的遞歸調用(如A->B->C->A),影響程序的可理解性;遞歸調用一般都占用較多的系統資源(如棧空間);遞歸調用對程序的測試有一定影響。故除非為某些算法或功能的實現方便,應減少沒必要的遞歸調用。
  
30 :仔細分析模塊的功能及性能需求,并進一步細分,同時若有必要畫出有關數據流圖,據此來進行模塊的函數劃分與組織
說明:函數的劃分與組織是模塊的實現過程中很關鍵的步驟,如何劃分出合理的函數結構,關系到模塊的最終效率和可維護性、可測性等。根據模塊的功能圖或/及數據流圖映射出函數結構是常用方法之一。
  
31 :改進模塊中函數的結構,降低函數間的耦合度,并提高函數的獨立性以及代碼可讀性、效率和可維護性
優化函數結構時,要遵守以下原則:
(1)不能影響模塊功能的實現。
(2)仔細考查模塊或函數出錯處理及模塊的性能要求并進行完善。
(3)通過分解或合并函數來改進軟件結構。
(4)考查函數的規模,過大的要進行分解。
(5)降低函數間接口的復雜度。
(6)不同層次的函數調用要有較合理的扇入、扇出。
(7)函數功能應可預測。
(8)提高函數內聚。(單一功能的函數內聚最高)
說明:對初步劃分后的函數結構應進行改進、優化,使之更為合理。 
  
32 :在多任務操作系統的環境下編程,要注意函數可重入性的構造
說 明:可重入性是指函數可以被多個任務進程調用。在多任務操作系統中,函數是否具有可重入性是非常重要的,因為這是多個進程可以共用此函數的必要條件。另 外,編譯器是否提供可重入函數庫,與它所服務的操作系統有關,只有操作系統是多任務時,編譯器才有可能提供可重入函數庫。如DOS下BC和MSC等就不具 備可重入函數庫,因為DOS是單用戶單任務操作系統。
  
33 :避免使用BOOL 參數
說明:原因有二,其一是BOOL參數值無意義,TURE/FALSE的含義是非常模糊的,在調用時很難知道該參數到底傳達的是什么意思;其二是BOOL參數值不利于擴充。還有NULL也是一個無意義的單詞。
  
34 : 對于提供了返回值的函數,在引用時最好使用其返回值 
  
35 :當一個過程(函數)中對較長變量(一般是結構的成員)有較多引用時,可以用一個意義相當的宏代替
說明:這樣可以增加編程效率和程序的可讀性。
示例:在某過程中較多引用TheReceiveBuffer[FirstSocket].byDataPtr,
則可以通過以下宏定義來代替:
# define pSOCKDATA TheReceiveBuffer[FirstScoket].byDataPtr



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=729126


posted on 2007-07-29 11:15 旅途 閱讀(234) 評論(0)  編輯 收藏 引用 所屬分類: C/C++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲高清中文字幕| 欧美激情一区二区三区在线| 亚洲一级特黄| 亚洲伦理在线免费看| 在线精品高清中文字幕| 韩国亚洲精品| 亚洲国产成人久久| 在线观看日韩av先锋影音电影院| 国产三级欧美三级| 尤物99国产成人精品视频| 有码中文亚洲精品| 夜夜嗨av一区二区三区网站四季av| 亚洲最新色图| 久久精彩免费视频| 欧美国产三区| 99精品久久久| 欧美亚洲三区| 嫩草国产精品入口| 国产精品激情电影| 久久综合伊人77777蜜臀| 亚洲福利视频二区| 99热免费精品| 性做久久久久久免费观看欧美| 欧美一区激情视频在线观看| 美国成人直播| 亚洲久久一区| 久久精品导航| 欧美日韩亚洲国产一区| 国产一区二区成人| 亚洲精品一二三区| 久久都是精品| 亚洲欧洲另类国产综合| 亚洲男人的天堂在线| 欧美福利精品| 国内自拍亚洲| 亚洲夜间福利| 亚洲黄色免费网站| 久久久久久久久久久久久女国产乱| 欧美精品免费播放| 国产一区二区三区成人欧美日韩在线观看 | 欧美一区二区啪啪| 欧美精品一区二区三区视频| 国产一区二区欧美日韩| 亚洲影院在线观看| 亚洲国产高清自拍| 欧美在线视频不卡| 国产精品美女| 亚洲一区二区欧美日韩| 亚洲电影免费观看高清完整版在线观看 | 午夜精品亚洲| 亚洲久久一区| 欧美日韩国产免费| 91久久久在线| 欧美激情亚洲激情| 欧美69视频| 91久久久在线| 亚洲精品1区2区| 欧美国产第一页| 亚洲精品国精品久久99热一| 免费在线播放第一区高清av| 久久国产天堂福利天堂| 国产午夜精品一区二区三区欧美| 亚洲欧美日韩国产成人| 一区二区三区四区国产| 国产精品草莓在线免费观看| 一区二区三区视频在线观看 | 国产欧美日韩免费| 亚洲欧美日韩国产中文| 一区二区三区久久| 国产精品美女久久久久久免费| 中文av字幕一区| 一本大道久久a久久精二百| 欧美日韩大片一区二区三区| 欧美激情国产高清| 99re66热这里只有精品3直播 | 黄色成人在线免费| 美女视频网站黄色亚洲| 久久―日本道色综合久久| 在线激情影院一区| 亚洲人成亚洲人成在线观看| 欧美精品激情| 午夜日本精品| 免费成人av| 亚洲影院一区| 久久久免费av| 在线一区二区三区四区| 亚洲资源av| 亚洲国内高清视频| 一本色道久久综合狠狠躁篇的优点| 国产精品国产福利国产秒拍| 欧美一区二区三区四区视频| 久久精品一本| 一本久久精品一区二区| 午夜电影亚洲| 亚洲美女啪啪| 欧美中文字幕在线播放| 亚洲精品日韩久久| 亚洲欧美久久| 亚洲乱码久久| 欧美一区二区日韩| 亚洲精品视频中文字幕| 亚洲欧美日韩国产中文| 亚洲人精品午夜| 欧美在线啊v一区| 一区二区三区欧美视频| 久久久精品国产一区二区三区 | 亚洲免费观看高清在线观看| 亚洲欧美国产高清| 亚洲精品久久在线| 欧美一区二视频| 亚洲在线成人精品| 欧美大片在线看免费观看| 久久精品理论片| 欧美精品自拍偷拍动漫精品| 久久久久久久一区| 国产精品美女黄网| 亚洲人成亚洲人成在线观看图片| 一区一区视频| 香蕉久久国产| 午夜精品久久久久久久99水蜜桃| 女女同性女同一区二区三区91| 久久久久亚洲综合| 国产精品一区在线播放| 99精品视频免费观看| 国产精品日日摸夜夜添夜夜av| 亚洲国产aⅴ天堂久久| 亚洲欧美成aⅴ人在线观看| 一本色道久久综合亚洲二区三区| 久久亚洲精品一区| 久久亚洲精品一区二区| 国产日韩专区| 欧美一级欧美一级在线播放| 午夜在线观看欧美| 国产精品久久久久av免费| 99热这里只有成人精品国产| 日韩一区二区免费高清| 欧美精品日韩三级| 亚洲人成网在线播放| 日韩视频欧美视频| 欧美日本在线看| 一区二区三区日韩| 欧美一区二区视频在线观看2020| 国产精品久久中文| 亚洲影院污污.| 久久精品人人做人人综合| 国产亚洲人成网站在线观看| 欧美一区二区三区四区在线观看地址| 校园春色国产精品| 国模套图日韩精品一区二区| 久久丁香综合五月国产三级网站| 久久九九热re6这里有精品| 国产在线国偷精品产拍免费yy| 久久精品卡一| 欧美激情91| 亚洲一区二区在线播放| 国产喷白浆一区二区三区| 久久精品日产第一区二区| 欧美v日韩v国产v| 亚洲精品影院| 国产精品久线观看视频| 久久精品国产亚洲5555| 亚洲第一在线综合网站| 亚洲综合另类| 在线播放精品| 欧美日韩高清区| 亚洲欧美中文在线视频| 美女亚洲精品| 亚洲视频免费| 国内精品视频一区| 欧美高清视频在线播放| 亚洲一区二区三区免费观看| 久久久久在线观看| 99综合电影在线视频| 国产欧美大片| 欧美成人日本| 亚洲欧美国产精品va在线观看| 猛干欧美女孩| 亚洲视频图片小说| 一区视频在线看| 国产精品va在线播放| 久久av一区二区三区漫画| 亚洲欧洲一区二区天堂久久| 欧美专区亚洲专区| 在线亚洲自拍| 亚洲第一主播视频| 国产精品视频大全| 欧美激情国产精品| 久久av红桃一区二区小说| 夜夜嗨av色综合久久久综合网| 久久最新视频| 久久av在线| 亚洲在线不卡| aa国产精品| 亚洲国产一区视频| 极品少妇一区二区三区| 国产精品素人视频| 欧美日韩国产成人在线免费| 久久嫩草精品久久久久| 国产资源精品在线观看| 欧美日韩综合在线免费观看|