2010-02-08 40 views
0

僅使用GOTO語句跳下來會有什麼壞處嗎?或者我們完全安全?使用GOTO語句只能跳轉出現的問題?

我的意思是覺得這是我的代碼,

Some code ... 
... 

GOTO whereToJump 

Some code ... 
... 

whereToJump: 

Some code ... 

當whereToJump點總是GOTO語句下面,有沒有安全問題?

+1

您將不得不對此進行擴展。目前還不清楚你的意思。一些示例代碼可能會有所幫助。 – 2010-02-08 13:37:52

+1

有多少GOTO問題會導致SO內爆? – 2010-02-08 13:42:23

+1

安全性在這裏不是問題。質量和可讀性是。 – 2010-02-08 13:48:03

回答

0

轉到不會讓代碼不那麼安全,不管你跳哪種方式。

您以任何喜歡的方式構建您的代碼。這是你的代碼決定代碼是好還是壞。 goto也許在某些情況下是適當的(不,我可以展示一個例子:-))

goto的問題是它可能會隱藏程序中的執行流程並使代碼混淆。但是,如果你創建容易閱讀/維護代碼,那麼這不是一個問題。

+1

'安全'不是正確的詞。我會說可讀性較差/難以理解/難以證明是正確的。 – Steven 2010-02-08 13:40:30

1

這是最着名的計算機科學論文之一的主題。 Dijkstra的Go To Statement Considered Harmful。它基本上表明,沒有人需要轉到(我知道有一些例外情況一如既往)。

它是1968年,但今天仍然非常可讀。

+0

它引發了最大的計算機科學slapfight有史以來,所以誰知道最後的結論是什麼... – Jimmy 2010-02-08 13:52:00

+5

我的goto有着名的名字 - 如果,當,切換。 – peterchen 2010-02-08 13:52:40

+0

本文是在一個非常不同的背景下編寫的。在那些日子裏,'goto'語句幾乎不受限制,就像在彙編代碼中一樣。也就是說,人們正在使用'goto'跳過節目中的所有地方。這相當於通過'goto'從一個函數跳到另一個函數。相比之下,C#的「goto」非常有限。這就是說,你確實沒有什麼需要。我認爲我從未在C#中遇到過碰到過「goto」是最佳選擇的案例。 – 2010-02-08 13:55:32

1

它是有道理的,只有向下的跳躍使得意大利麪條代碼的潛力大大降低。 (根據我的經驗,在調試遺留的基於GOTO的代碼時,75%的頭痛來自於這種情況,當向上的gotos導致混亂的循環時)

但是,考慮到你只使用向下跳轉,應該很容易轉換爲不基於代碼的代碼。我不確定有多少改進你的gotos會提供。

+1

轉發goto的仍然是一個簡單的裝置,可以突破嵌套塊。 – peterchen 2010-02-08 13:53:41

1

在一個更復雜的例子中,當然如果你決定只使用GOTO來跳轉在相同的範圍,你可以使用if語句。 (如果它不在同一個範圍內,它不是真的「只是向前跳躍」,是嗎?)

(當然,如果你的真實代碼不是那麼複雜,那麼你可以擺脫那個第二塊「部分代碼...」)

0

好吧,這裏真的沒有問題。該代碼相當於:

Some code ... 
... 

if (false) 
{ 
Some code ... 
... 
} 

Some code ... 

這就是說,我不會這樣做。 goto的好用例非常少見,而其他流控構造在C#中更具慣用性。

1

現在應該避免GOTO的主要原因是程序員一般不再習慣GOTO(這是一件好事)。因此,如果您編寫廣泛使用GOTO的代碼,那麼您的同行程序員很可能難以理解並擴展它。

更糟的是,這裏和那裏的GOTO可能會導致破窗綜合症,因爲同事們開始使用越來越多的GOTO,直到您剩下一大碗意大利麪。

xkcd說得最好...

alt text

1

我使用goto語句時需要它JUMB從向下許多地方的代碼塊。通常沒有goto語句,這可能需要編寫另一個函數(以便上面的代碼塊在第一個函數中不重複)並在第一個函數內部調用。 goto的效率不及if或switch語句,因爲它還利用if,switch等使用的jumb語句之一(jz,jnz等)。

0

有了這個評論,我不鼓勵使用的GOTO,但只是爲了表明在某些特定情況下它可能有用。到目前爲止,在實踐中我還沒有看到任何使用goto語句的代碼向上或向下跳轉,但有一個特定的用例,我發現goto更具可讀性。這裏是一個代碼示例,我認爲goto更有意義。

void fun_test() 
{ 
    .code.. 
    allocate dynamic memory. 
    acquire_lock(); 

    //do some action, call api. 
    if (some error) { 
     print error; 
     free memory; 
     unlock(); 
     return FAIL; 
    } else { 
     // some code. 
    } 

    if (some_other error) { 
     print error; 
     free memory; 
     unlock(); 
     return FAIL; 
    } 
    : 
    : 
    // more error condition checks. 
    : 
    return SUCCESS 

} 

void fun_test_withgoto() 
{ 
    error_code rc = SUCCESS; 
    .code.. 
    allocate dynamic memory. 
    acquire_lock(); 

    //do some action, call api. 
    if (some error) { 
     rc = <Failure id>; 
     goto function_cleanup; 
    } else { 
     // some code. 
    } 

    if (some_other error) { 
     rc = <failure id>; 
     goto function_cleanup;  
    } 
: 
: 
// more error conditions. 
: 

function_cleanup: 
    if (rc == SUCCESS) { 
     print "Success.."; 
    } else { 
     print "Error : <failure id>"; 
    } 
    free_memory(); 
    unlock(); 
    return(rc); 
}