關于C語言的goto語句存在很多爭議,很多書籍都建議“謹慎使用,或者根本不用”。Linux之父Linus在Linux中大量使用goto,也是在啟示著我們可以合理使用goto語句。
存在即合理,既然是C語言中的一個知識點,我們還是有必要學會使用。先看一些goto如何用:
一、goto的基本語法
goto語句有兩部分:goto和標簽名。標簽的命名規(guī)則與變量的命名規(guī)則一樣。如:
goto label;
要讓這條語句正常工作,函數還必須包含另一條標為label的語句,該語句以標簽名后緊跟一個冒號開始,如:
label:printf("goto here.\n");
二、goto的例子
/*
編譯環(huán)境:mingw32 gcc6.3.0
*/ #include #include /* goto測試 */ void TestGoto(void) { int i; while (1)
????{ for (i = 0; i < 10; i++)
{ if (i > 6)
????{ goto label;
????} printf("%s : i = %d\n", __FUNCTION__, i);
}
????}
label: printf("test goto end!");
} int main(void) {
TestGoto();
}
運行結果:
從運行結果我們明顯可以知道goto用法,可以跳出多重循環(huán),程序執(zhí)行過程中遇到goto語句就可以跳轉到label處繼續(xù)執(zhí)行。
值得注意的一點是:goto語句與其跳轉的標簽處必須在同一個函數內。
三、goto與break、continue的區(qū)別?
同樣是跳轉語句,goto語句與break、continue語句有什么區(qū)別呢?
實際上,break和continue是goto的特殊形式。使用break與continue的好處是:其名稱已經表明他們的用法。
下面通過代碼實例看一下break與continue的用法:
1、break測試函數
使用上面的測試程序,建一個測試break語句的函數void TestBreak(void);,如:
/* break測試 */ void TestBreak(void) { int i; while (1)
????{ for (i = 0; i < 10; i++)
{ if (i > 6)
????{ break; /* 第一個break:跳出for循環(huán) */ } printf("%s : i = %d\n", __FUNCTION__, i);
} printf("Now i = %d\n", i); break; /* 第一個break:跳出while循環(huán) */ } printf("test break end!");
}
運行結果:
從運行結果我們明顯可以知道,break可以退出當前循環(huán)。
在本例子中,第一個break語句退出當前的for循環(huán),第二個break語句退出當前的while循環(huán)??梢姡粋€break可退出一層循環(huán)。
所以,根據break與goto的特點知道,如果是跳出很多層循環(huán),使用goto會方便些。
2、continue測試函數
同樣的,建一個測試continue語句的函數void TestContinue(void);,如:
/* continue測試 */ void TestContinue(void) { int i; for (i = 0; i < 10; i++)
????{ if (i > 6)
{ printf("i = %d, continue next loop\n", i); continue; /* continue:結束本次循環(huán)(而不是終止這一層循環(huán))繼續(xù)進入下一次循環(huán) */ } printf("%s : i = %d\n", __FUNCTION__, i);
????} printf("test break end!");
}
運行結果:
從運行結果我們明顯可以知道,continue可以結束本次循環(huán)(而不是整個循環(huán))而進入下一次循環(huán)(i所代表的就是循環(huán)的次數)。
四、支持與反對goto的理由是什么?
1、不提倡使用goto
不提倡使用goto的占比應該比較多,不提倡的原因主要是:很容易把邏輯弄亂且難以理解。
2、使用goto的理由
這一部分人認為goto可以用在以下兩種情況比較方便:
(1)跳出多層循環(huán)。
這個例子就類似于我們上面的goto測試程序。
(2)異常處理。
一個函數的執(zhí)行過程可能會產生很多種情況異常情況。下面有幾種處理方式,以代碼為例:
方法一:做出判斷后,如果條件出錯,直接return。
int mystrlen(char *str) { int count = 0; if (str == NULL)
{ return -1;
} if (*str == 0)
{ return 0;
} while(*str != 0 )
{
count++;
str++;
} return count;
}
方法二:先設置一個變量,對變量賦值,只有一個return。
int mystrlen(char *str) { int ret; if (str == NULL)
{
ret = -1;
} else if (*str == 0)
{
ret = 0;
} else {
ret = 0; while(*str != 0 )
{
ret++;
str++;
}
} return ret;
}
方法三:使用goto語句。
int mystrlen(char *str) { int ret; if (str == NULL)
{
ret = -1; goto _RET;
} if (*str == 0)
{
ret = 0; goto _RET;
} while(*str !=0 )
{
ret++;
str++;
}
_RET: return ret;
}
其中,方法三就是很多人都提倡的方式。統(tǒng)一用goto err跳轉是最方便且效率最高的,從反匯編語句條數可以看出指令用的最少,消耗的寄存器也最少,效率無疑是最高的。
并且,使用goto可以使程序變得更加可擴展。當程序需要在錯誤處理時釋放資源時,統(tǒng)一到goto處理最方便。這也是為什么很多大型項目,開源項目,包括Linux,都會大量的出現goto來處理錯誤!
以上就是關于goto語句的基本使用、goto與break、continue的區(qū)別的總結,如有錯誤,歡迎指出!如果覺得不錯可以幫忙分享~
參考資料:
1、《C Primer Plus》 2、https://www.cnblogs.com/trying/archive/2012/06/25/2863753.html
推薦閱讀: FILE、LINE等幾種C標準用法
su、sudo、sudo su、sudo -i使用和區(qū)別
百度網盤國際版 Dubox 干凈好用,卻與國內用戶無緣
關注 微信公眾號『strongerHuang』,后臺回復“1024”查看更多內容,回復“加群”按規(guī)則加入技術交流群。
長按前往圖中包含的公眾號關注
免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯系我們,謝謝!





