建议16:慎用goto
如果说有一个关键字在C/C++(www.cppentry.com)语言程序中备受争议,那么非程序跳转关键字goto莫属。在早期的BASIC和FORTRAN语言中,goto备受依赖,为了照顾部分程序员的设计习惯,在C语言中goto关键字依然得到了保留。然而,与前面两种语言有所不同,goto在C/C++(www.cppentry.com)语言中就像一个多余的外来户,有没有它几乎不影响C语言程序的设计与运行,它没有带来太大的正面作用,相反却容易破坏程序的结构性。所以,Kernighan和Ritchie认为goto语句“非常容易被滥用”,并且建议“一定要谨慎使用,或者干脆不用”。
之所以建议避免使用goto,是因为C/C++(www.cppentry.com)语言中提供了更好的方式去实现goto的功能。为了帮助部分程序员克服goto依赖症,接下来我会分别介绍以下情形下goto语句的替换方式:
if控制内的多条语句
如果熟悉旧风格的BASIC和FORTRAN,会知道只有紧跟在if条件后的那一条语句才属于该if的控制域,所以就出现了以下goto的使用形式:
- Size = 20;
- Flag = 1;
- if( price > 15)
- goto A_PLAN;
- goto B_PLAN;
- A_PLAN:
- Size /=2;
- Flag = 3;
- B_PLAN:
- Money = price * Size * Flag;
而在C/C++(www.cppentry.com)语言中,复合语句或代码块很容易实现上述目的,而且使代码更加清晰可读,如下所示:- Size = 20;
- Flag = 1;
- if( price > 15)
- {
- Size /=2;
- Flag = 3;
- }
- Money = price * Size * Flag;
不确定循环
首先请看如下代码:
- ReadScore:
- scanf("%d", &Score);
- if(Score < 0 )
- goto ErrorStage;
- ... // Processing codes
- goto ReadScore;
- ErrorStage:
- ... // Error Processing
这种情形可以用我们熟知的while循环来完美代替:- scanf("%d", &Score);
- while(Score >= 0)
- {
- ... // Processing codes
- scanf("%d", &Score);
- }
此外,如果跳转到循环结尾会开始新一轮循环,可以使用continue代替;如果要跳出循环,那就使用break。
上述goto语句破坏了程序的结构性,影响了程序的可读性,这在C/C++(www.cppentry.com)程序员看来是难以容忍的。然而,有一种goto的使用情形为许多C/C++(www.cppentry.com)程序员所接受,那就是程序在一组嵌套循环中出现错误,无路可走时的跳转处理,如下所示:
- while(... )
- {
- for(...)
- {
- for(...)
- {
- Processing statement;
- if(error)
- goto ERROR;
- }
- More processing statement;
- }
- Yet more processing statement;
- }
- And more processing statement;
- ERROR:
- Deal_With_Error Statement;
请记住:
过度使用goto会使代码流程错综复杂,难以理清头绪。所以,如果不熟悉goto,不要使用它;如果已经习惯使用它,试着不去使用。