2013-10-27 22 views
2

我個人總是用函數檢查函數中的值,但在我們的大學裏,一位老師希望我們經常檢查函數外的值。我認爲如果我們要使用相同的檢查值多次調用函數,那麼檢查函數外部的一個時間值可能是一個好主意。但是,如果您忘記檢查臨界值,則可能會在程序中出現分割錯誤等錯誤。檢查函數內部的值vs外部?

我粘貼了我正在處理的代碼。在學校,我們應該檢查功能以外的值,但我認爲這是瘋狂的,浪費時間在這種情況下。主函數在代碼的最後,當檢查malloc的返回值(函數外的init_unsecure和函數內部的init_secure)時,或者在刪除元素之前檢查它是否存在時,可以看到區別(remove_unsecure在重複函數之外函數內部的存在函數和remove_secure中的while循環)。

您認爲如何?檢查函數內的值不是很明顯嗎?

#include <stdlib.h> 

typedef struct strens 
{ 
    int  v[100]; 
    int  n; 
}  StrEns, *Ens; 

// init struct pointer (need to check if return value is not NULL) 
Ens init_unsecure() 
{ 
    Ens e; 

    if ((e = malloc(sizeof(StrEns))) != NULL) 
    e->n = 0; 
    return e; 
} 

// init struct pointer and check if malloc is not NULL 
Ens init_secure() 
{ 
    Ens e; 

    if ((e = malloc(sizeof(StrEns))) == NULL) 
    exit(EXIT_FAILURE); 
    e->n = 0; 
    return e; 
} 

// insert element 
Ens insert(Ens e, int x) 
{ 
    e->v[e->n] = x; 
    ++e->n; 
    return e; 
} 

// return if element exists or not 
int exists(Ens e, int x) 
{ 
    int i = 0; 
    while (i < e->n && e->v[i] != x) 
    ++i; 
    return (i != e->n); 
} 

// remove element (need to check if element exists before) 
Ens remove_unsecure(Ens e, int x) 
{ 
    --e->n; 
    int i = 0; 
    while (e->v[i] != x) 
    ++i; 
    e->v[i] = e->v[e->n]; 
} 

// remove element if exists 
Ens remove_secure(Ens e, int x) 
{ 
    --e->n; 
    int i = 0; 
    while (i < e->n && e->v[i] != x) 
    ++i; 
    e->v[i] = e->v[e->n]; 
} 

// comparing init_unsecure vs init_secure && remove_unsecure vs remove_secure 
int main() 
{ 
    Ens e1, e2, e3; 

    if ((e1 = init_unsecure()) == NULL) 
    return EXIT_FAILURE; 
    if ((e2 = init_unsecure()) == NULL) 
    return EXIT_FAILURE; 
    if ((e3 = init_unsecure()) == NULL) 
    return EXIT_FAILURE; 

    e1 = init_secure(); 
    e2 = init_secure(); 
    e3 = init_secure(); 

    if (exists(e1, 42)) 
    remove_unsecure(e1, 42); 
    if (exists(e2, 42)) 
    remove_unsecure(e2, 42); 
    if (exists(e3, 42)) 
    remove_unsecure(e3, 42); 

    remove_secure(e1, 42); 
    remove_secure(e2, 42); 
    remove_secure(e3, 42); 

    return EXIT_SUCCESS; 
} 

回答

1

的C編程(仍然)當時的心態是你的函數調用者知道他正在做什麼,因此應當提供有效的論點。不這樣做被廣泛接受是未定義行爲的原因。

例如,free不必驗證您傳遞的指針之前是否已由malloc返回,因爲這會影響性能。只要調用你的函數的代碼是正確的,並在預期的範圍內提供了每個參數,即使沒有在函數內部進行防禦性檢查,一切都應該是確定的。

儘管如此,仍然建議在整個代碼中聲明斷言,以便作爲程序員的您儘可能早地捕獲異常。

+0

你說得對,我同意......該工具不使用用戶。用戶使用該工具。 ;) –

+0

所以你不會檢查值,因爲沒有錯誤。只要沒有用戶輸入,那麼你會怎麼做?例如,用戶給出一個數字作爲參數移除。如果你不想要一個無限循環,你必須檢查它是否存在或檢查函數,我< e-> n。那麼,檢查裏面的功能比較好,你同意嗎? cc @JoeDF – baptx

+0

當涉及到用戶輸入時,您應該始終驗證它。處理輸入的代碼應該最有可能驗證它,而程序的其他部分被設計爲高效且可用,無論是否具有用戶輸入。 –