<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 設計應用 > 嵌入式C中的goto語(yǔ)句,爭議很大

嵌入式C中的goto語(yǔ)句,爭議很大

作者: 時(shí)間:2024-03-21 來(lái)源:網(wǎng)絡(luò ) 收藏

什么是?

 被稱(chēng)為 C 語(yǔ)言中的跳轉,用于無(wú)條件跳轉到其他標簽。它將控制權轉移到程序的其他部分。

本文引用地址:http://dyxdggzs.com/article/202403/456669.htm

 語(yǔ)句一般很少使用,因為它使程序的可讀性和復雜性變得更差。

語(yǔ)法

goto label;

goto 語(yǔ)句示例

讓我們來(lái)看一個(gè)簡(jiǎn)單的例子,演示如何使用 C 語(yǔ)言中的 goto 語(yǔ)句。

打開(kāi) Visual Studio 創(chuàng )建一個(gè)名稱(chēng)為:goto 的工程,并在這個(gè)工程中創(chuàng )建一個(gè)源文件:goto-statment.c,其代碼如下所示:

#include   void main(){  int age;gotolabel:  printf("You are not eligible to vote!n");  printf("Enter you age:n");  scanf("%d", &age);  if (age < 18)   {   goto gotolabel;  }  else  {   printf("You are eligible to vote!n");  }}

執行上面代碼,得到以下結果

You are not eligible to vote!Enter you age:12You are not eligible to vote!Enter you age:18You are eligible to vote!

為什么它這么不受待見(jiàn)?

二十幾年前,當計算機編程尚處于起步階段時(shí),程序流程是由 “GOTO” 語(yǔ)句來(lái)控制。該類(lèi)語(yǔ)句允許程序員對當前代碼行斷行,而直接進(jìn)入另一個(gè)不同的代碼段。

下圖為簡(jiǎn)單的示例。

640.png

編程語(yǔ)言終究開(kāi)始引入了函數的概念,即允許程序對代碼進(jìn)行斷行。如果已經(jīng)完成,不再使用 goto 語(yǔ)句來(lái)表示代碼的斷行。

函數調用后,函數將回到下一條指令。下圖為示例。

640-2.png

這一做法改善了程序結構,提高了可讀性。自此,這被視為編寫(xiě)程序的正確方法。只要看到或想到 goto 語(yǔ)句,就會(huì )讓軟件工程師退縮,產(chǎn)生本能的厭惡。

在 wikipedia 上的解釋就是:

GOTO語(yǔ)句一直是批評和爭論的目標,主要的負面影響是使用GOTO語(yǔ)句使程序的可讀性變差,甚至成為不可維護的「面條代碼」。

隨著(zhù)結構化編程在二十世紀六十年代到七十年代變得越來(lái)越流行,許多計算機科學(xué)家得出結論,即程序應當總是使用被稱(chēng)為「結構化」控制流程的命令,以及 if-then-else 語(yǔ)句來(lái)替代 GOTO。甚至在今天,許多程序風(fēng)格編碼標準禁止使用 GOTO 語(yǔ)句。

也有不少人為 GOTO 語(yǔ)句辯護,他們認為只要加以限制地使用 GOTO 語(yǔ)句不會(huì )導致低質(zhì)量的代碼,并且在許多編程語(yǔ)言中,一些功能難以在不使用 GOTO 語(yǔ)句的情況下實(shí)現。比如有限狀態(tài)機的實(shí)現、跳出嵌套循環(huán)以及異常處理等等。

大概最著(zhù)名的對于 GOTO 的批評是艾茲格·迪杰斯特拉(Edsger Wybe Dijkstra)在1968年的一篇名為《GOTO陳述有害輪》的論文。

迪杰斯特拉認為不加限制地使用GOTO語(yǔ)句應當從高級語(yǔ)言中廢止,因為它使分析和驗證程序正確性(特別是涉及循環(huán))的任務(wù)變得復雜。

另外一種觀(guān)點(diǎn)出現在高德納的Structured Programming with go to Statements中,文章分析了許多常見(jiàn)編程任務(wù),然后發(fā)現其中的一些使用GOTO將得到最理想的結構。

限制GOTO

許多語(yǔ)言,如 C 語(yǔ)言和 Java,提供了相關(guān)的控制流語(yǔ)句,如 break 和 continue,它們都是有效地被限制的 goto 語(yǔ)句。它們的作用是無(wú)條件跳轉,但是只能夠跳到循環(huán)塊結束的位置 —— 繼續進(jìn)入下一循環(huán)(continue)或者結束循環(huán)(break)。

switch/case結構

C 語(yǔ)言、C++ 和 Java 中的 switch 語(yǔ)句高效地實(shí)現了一個(gè)多路 goto,跳轉目標由表達式的值來(lái)選擇。這也導致了我們沒(méi)有不得不使用 goto 的理由。

針對這些,導致目前 goto 的使用情況是這樣的:goto 語(yǔ)句的結果在C/C++等高級編程語(yǔ)言中保留了goto語(yǔ)句,但被建議不用或少用。

在一些更新的高級編程語(yǔ)言,如 Java 不提供 goto 語(yǔ)句,它雖然指定 goto 作為關(guān)鍵字,但不支持它的使 用,使程序簡(jiǎn)潔易讀;盡管如此后來(lái)的 c# 還是支持 goto 語(yǔ)句的,goto 語(yǔ)句一個(gè)好處就是可以保證程序存在唯一的出口,避免了過(guò)于龐大的 if 嵌套。

另一方面,goto 語(yǔ)句只是不提倡,當然不是禁用,那么在什么情況下可以使用 goto 語(yǔ)句呢?

可以考慮使用 goto 的情形:

· 從多重循環(huán)中直接跳出 ;

· 出錯時(shí)清除資源;

· 可增加程序的清晰度的情況。

不加限制地使用 goto:破壞了清晰的程序結構,使程序的可讀性變差,甚至成為不可維護的"面條代碼"。

經(jīng)常帶來(lái)錯誤或隱患,比如它可能跳過(guò)了某些對象的構造、變量的初始化、重要的計算等語(yǔ)句。

下列關(guān)于使用 goto 語(yǔ)句的原則可以供讀者參考。

1. 使用 goto 語(yǔ)句只能 goto 到同一函數內,而不能從一個(gè)函數里 goto 到另外一個(gè)函數里。

2. 使用 goto 語(yǔ)句在同一函數內進(jìn)行 goto 時(shí),goto 的起點(diǎn)應是函數內一段小功能的結束處,goto 的目的 label 處應是函數內另外一段小功能的開(kāi)始處。

3. 不能從一段復雜的執行狀態(tài)中的位置 goto 到另外一個(gè)位置,比如,從多重嵌套的循環(huán)判斷中跳出去就是不允許的。

4. 應該避免像兩個(gè)方向跳轉。這樣最容易導致"面條代碼"。

閱讀過(guò) linux 內核代碼的同學(xué)應該注意到,linux 內核代碼里面其實(shí)有不少地方用了 goto 語(yǔ)句,

這是在/drivers/i2c/i2c-dev.c中的i2c_dev_init函數:

static int __init i2c_dev_init(void){ int res; pr_info("i2c /dev entries drivern"); res = register_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS, "i2c"); if (res)  goto out; i2c_dev_class = class_create(THIS_MODULE, "i2c-dev"); if (IS_ERR(i2c_dev_class))  {  res = PTR_ERR(i2c_dev_class);  goto out_unreg_chrdev; } i2c_dev_class->dev_groups = i2c_groups; /* Keep track of adapters which will be added or removed later */ res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier); if (res)  goto out_unreg_class; /* Bind to already existing adapters right away */ i2c_for_each_dev(NULL, i2cdev_attach_adapter); return 0;out_unreg_class: class_destroy(i2c_dev_class);out_unreg_chrdev: unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);out: pr_err("Driver Initialisation failedn"); return res;}

但是你會(huì )發(fā)現,這些地方的goto語(yǔ)句,使用非常謹慎,基本都遵循上面提到的幾個(gè)原則。

本文來(lái)源網(wǎng)絡(luò ),免費傳達知識,版權歸原作者所有。如涉及作品版權問(wèn)題,請聯(lián)系我進(jìn)行刪除。



關(guān)鍵詞: 嵌入式 C語(yǔ)言 goto 語(yǔ)句

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>