以下來自新浪部落格的轉載:
1:為何不提倡使用goto語句?
淵源(來自wikipedia):
GOTO是一條可以在許多電腦程式設計語言中找到的語句。它是英文單詞go和to的組合。當執行這條語句的時候,它將控制流程程無條件地轉到另一條語句(也叫"跳轉")。跳躍陳述式需要指明標記,在不同語言中,標記可以是標識符或行號。在機器碼層級,goto是一種分支的形式。
在一些語言中,可以不用顯示地使用goto關鍵字而實現同樣的功能,例如break或continue關鍵字可以跟隨一個標識符。SNOBOL語言支援一種語句的尾碼形式,可以在本條語句執行完畢後實現無條件跳轉。
GOTO語句被大部分進階語言支援,只有很少的進階語言不支援GOTO語句。例如,goto是一個Java語言的保留字,但是不允許使用。例如Pascal中沒有Goto,但可用procedure執行一外加文法。
GOTO語句一直是批評和爭論的目標,主要的負面影響是使用GOTO語句使程式的可讀性變差,甚至成為不可維護的“麵條代碼”。隨著結構化編程在二十世紀六十年代到七十年代變得越來越流行,許多電腦科學家得出結論,即程式應當總是使用被稱為“結構化”控制流程程的命令,如迴圈以及if-then-else語句來替代GOTO。甚至在今天,許多程式風格編碼通訊協定禁止使用GOTO語句。為GOTO語句辯護的人認為,加以限制地使用GOTO語句不會導致低品質的代碼,並且聲稱在許多程式設計語言中,一些任務如果不使用一條或多條GOTO語句是無法被直接實現的。如有限狀態自動機的實現、跳出嵌套迴圈以及異常處理。
大概最著名的對於GOTO的批評是艾茲格·迪傑斯特拉(Edsger Wybe Dijkstra)在1968年的一篇名稱為《GOTO陳述有害論(英語:Go
To Statement Considered Harmful)》的論文。[2]迪傑斯特拉認為不加限制地使用GOTO語句應當從進階語言中廢止,因為它使分析和驗證程式正確性(特別是涉及迴圈)的任務變得複雜。另外一種觀點高德納的Structured
Programming with go to Statements [3]中,文章分析了許多常見編程任務,然後發現其中的一些使用GOTO將得到最理想的結構。
這些批評在一些程式設計語言的設計上起到了效果。雖然Ada語言的設計者在二十世紀七十年代晚期意識到了對於GOTO的批評,這條語句仍舊被包含進去,主要是用來支援自動產生那些goto語句必不可少的代碼。[4]但是,作為goto語句目的地的標籤必須使用雙角括弧括起來(如:<<Start_Again>>),而這個文法在其他語言中都不被使用。這使得檢查程式中goto目的地的存在變得容易。goto語句本身使用簡單的形式goto Start_Again;.
原因: GOTO語句使程式的靜態結構和動態結構不一致,從而使程式難以理解,難以查錯。
有人認為GOTO語句使用起來比較靈活,而且有些情形能提高程式的效率。
1974年,D·E·克努斯對於GOTO語句爭論作了全面公正的評述,其基本觀點是:不加限制地使用GOTO語句,特別是使用往回跳的GOTO語句,會使程式結構難於理解,在這種情形,應盡量避免使用GOTO語句。但在另外一些情況下,為了提高程式的效率,同時又不至於破壞程式的良好結構,有控制地使用一些GOTO語句也是必要的。用他的話來說就是:“在有些情形,我主張刪掉GOTO語句;在另外一些情形,則主張引進GOTO語句。”
後來,G·加科皮尼和C·波姆從理論上證明了:任何程式都可以用順序、分支和重複結構表示出來。這個結論表明,從進階程式語言中去掉GOTO語句並不影響進階程式語言的編程能力,而且編寫的程式的結構更加清晰。
goto語句的結果:在C/C++等進階程式設計語言中保留了goto語句,但被建議不用或少用。在一些更新的進階程式設計語言,如Java不提供goto語句,它雖然指定goto作為關鍵字,但不支援它的使 用,使程式簡潔易讀;儘管如此後來的c#還是支援goto語句的,goto語句一個好處就是可以保證程式存在唯一的出口,避免了過於龐大的if嵌套。
可以考慮使用goto的情形:1.從多重迴圈中直接跳出 ;2. 出錯時清除資源; 3.可增加程式的清晰度的情況。
不加限制地使用goto:破壞了清晰的程式結構,使程式的可讀性變差,甚至成為不可維護的"麵條代碼"。經常帶來錯誤或隱患,比如它可能跳過了某些對象的構造、變數的初始化、重要的計算等語句。
goto語句問題的提出直接推動了結構化程式設計(structured programming)的思想和程式設計方法學的誕生和發展。結構化程式設計方法引入了工程思想和結構化思想,使大型軟體的開發和編程都得到了極大的改善。結構化程式設計方法的主要原則可以概括為自頂向下,逐步求精,模組化,限制使用goto語句。
下列關於使用goto語句的原則可以供讀者參考。 1) 使用goto語句只能goto到同一函數內,而不能從一個函數裡goto到另外一個函數裡。 2) 使用goto語句在同一函數內進行goto時,goto的起點應是函數內一段小功能的結束處,goto的目的label處應是函數內另外一段小功能的開始處。 3) 不能從一段複雜的執行狀態中的位置goto到另外一個位置,比如,從多重嵌套的迴圈判斷中跳出去就是不允許的。 4)應該避免像兩個方向跳轉。這樣最容易導致"麵條代碼"。
2:網友熱心回答
goto並不是不能用,關鍵是goto指向的標籤必須在goto這行的後面。
盲目禁用goto是不對的。
見傑拉爾德·溫伯格《理解專業程式員》
如果要做軟體開發的話,特別是團隊的話,為了將來項目的維護和讓代碼通俗易懂,最好不要用goto;
goto會影響編譯器最佳化,還有九成的goto都可以轉換成不用goto的方式
如果GOTO的語句在後面就不會出現死迴圈!
如果GOTO的語句在前面就很容易死迴圈!!!
還有,GOTO 的語句都能用REPEAT或WHILE來代替!
所以,一般不用GOTO!!
因為那會擾亂編程結構次序
3:
正面:
goto語句在C/C++語言中可謂是“臭名昭著”,乃至有的書(或公司的編程規範)提出禁用goto語句的說法。其結果就是,造成有的程式員一看到goto語句在某程式中被使用,就本能地認為這個程式寫得很“垃圾”。此外,也使得有些程式員因為使用了goto語句而覺得自己很不專業。其實,凡事都不能太偏激,goto語句運用得好能大大地簡化程式,以及提高程式的可讀性和可維護性。在開始樣本其好處之前,先用一些統計資料來說明goto語句並沒有因為“臭名昭著”而被拋棄,這些統計資料可能並不是百分之百的精確,但很具有說服力。對於作業系統,Linux-2.6.21核心使用了20,333個goto語句,VxWorks-6.2則使用了9142個,最後941個goto語句被運用到了rtems-4.9.2中;另外,glibc-2.9庫使用了1750個goto語句。所有這些統計資料都表明,goto語言並沒有想象的那樣可怕而招到禁用,其關鍵在於
—— 恰當地運用它。
轉載來自:http://blog.sina.com.cn/s/blog_6908039c0101f5hx.html
以下來自csdn部落格的轉載:
goto只能在函數體內跳轉,不能跳到函數體外的函數。即goto有局部範圍,需要在同一個棧內。
需要在要跳轉到的程式段起始點加上標號。如下例中的part2。
1.goto 語句可用於跳出深嵌套迴圈
[cpp]
view plaincopyprint?
- #include<iostream>
- using namespace std;
- int main()
- {
- for(int i=0;i<10;i++)
- for(int j=0;j<10;j++)
- for(int k=0;k<10;k++)
- {
- cout<<i*j*k<<" ";
- if(216==i*j*k)
- goto part2;//break是跳不出多重迴圈的
- }
- cout<<"此處被省略"<<endl;
- part2:
- cout<<"part2"<<endl;
- system("pause");
- }
#include<iostream>using namespace std;int main(){for(int i=0;i<10;i++) for(int j=0;j<10;j++) for(int k=0;k<10;k++) { cout<<i*j*k<<" "; if(216==i*j*k) goto part2;//break是跳不出多重迴圈的 } cout<<"此處被省略"<<endl; part2: cout<<"part2"<<endl; system("pause");}
2.goto語句可以往後跳,也可以往前跳
[cpp]
view plaincopyprint?
- #include<iostream>
- using namespace std;
-
- int main()
- {
- int x,sum=0;
- //定義標號L1
- L1: cout<<"x=";
- cin>>x;
- if (x==-1)
- goto L2; //當使用者輸入-1時,轉到L2語句處
- else
- sum+=x;
- goto L1; //只要使用者沒有輸入-1,則轉到L1語句處,程式一直將使用者的輸入默默地累加到變數sum中。
- //定義標號L2
- L2: cout<<"sum="<<sum<<endl;//一旦轉到L2,將輸出累計結果,程式運行結束。
- system("pause");
- }
#include<iostream>using namespace std;int main(){ int x,sum=0; //定義標號L1L1: cout<<"x="; cin>>x; if (x==-1) goto L2; //當使用者輸入-1時,轉到L2語句處 else sum+=x; goto L1; //只要使用者沒有輸入-1,則轉到L1語句處,程式一直將使用者的輸入默默地累加到變數sum中。 //定義標號L2L2: cout<<"sum="<<sum<<endl;//一旦轉到L2,將輸出累計結果,程式運行結束。 system("pause");}
3.也可以跳出switch,或者在case之間進行跳轉
如:
[cpp]
view plaincopyprint?
- #include<iostream>
- using namespace std;
-
- int main()
- {
- char a;
- L1:
- cout<<"請輸入一個字元"<<endl;
- cin>>a;
- switch(a)
- {
- case 'a':
- cout<<"case a"<<endl;
- goto L1;
- //break;
- L2:
- case 'b':
- cout<<"case b"<<endl;
- break;
- case 'c':
- cout<<"case c"<<endl;
- // break;
- goto L2;
- default:
- break;
- }
- system("pause");
- }
-
#include<iostream>using namespace std;int main(){char a;L1:cout<<"請輸入一個字元"<<endl;cin>>a;switch(a){ case 'a': cout<<"case a"<<endl; goto L1; //break; L2: case 'b': cout<<"case b"<<endl; break; case 'c': cout<<"case c"<<endl; // break; goto L2; default: break;} system("pause");}
轉載來自:http://blog.csdn.net/generalhking/article/details/8011306