嵌入式C中的goto语句,争议很大

发布时间:2024-03-21  

什么是?

 被称为 C 语言中的跳转,用于无条件跳转到其他标签。它将控制权转移到程序的其他部分。

本文引用地址:

 语句一般很少使用,因为它使程序的可读性和复杂性变得更差。

语法

goto label;

goto 语句示例

让我们来看一个简单的例子,演示如何使用 C 语言中的 goto 语句。

打开 Visual Studio 创建一个名称为:goto 的工程,并在这个工程中创建一个源文件: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!

为什么它这么不受待见?

二十几年前,当计算机编程尚处于起步阶段时,程序流程是由 “GOTO” 语句来控制。该类语句允许程序员对当前代码行断行,而直接进入另一个不同的代码段。

下图为简单的示例。

640.png

编程语言终究开始引入了函数的概念,即允许程序对代码进行断行。如果已经完成,不再使用 goto 语句来表示代码的断行。

函数调用后,函数将回到下一条指令。下图为示例。

640-2.png

这一做法改善了程序结构,提高了可读性。自此,这被视为编写程序的正确方法。只要看到或想到 goto 语句,就会让软件工程师退缩,产生本能的厌恶。

在 wikipedia 上的解释就是:

GOTO语句一直是批评和争论的目标,主要的负面影响是使用GOTO语句使程序的可读性变差,甚至成为不可维护的「面条代码」。

随着结构化编程在二十世纪六十年代到七十年代变得越来越流行,许多计算机科学家得出结论,即程序应当总是使用被称为「结构化」控制流程的命令,以及 if-then-else 语句来替代 GOTO。甚至在今天,许多程序风格编码标准禁止使用 GOTO 语句。

也有不少人为 GOTO 语句辩护,他们认为只要加以限制地使用 GOTO 语句不会导致低质量的代码,并且在许多编程语言中,一些功能难以在不使用 GOTO 语句的情况下实现。比如有限状态机的实现、跳出嵌套循环以及异常处理等等。

大概最著名的对于 GOTO 的批评是艾兹格·迪杰斯特拉(Edsger Wybe Dijkstra)在1968年的一篇名为《GOTO陈述有害轮》的论文。

迪杰斯特拉认为不加限制地使用GOTO语句应当从高级语言中废止,因为它使分析和验证程序正确性(特别是涉及循环)的任务变得复杂。

另外一种观点出现在高德纳的Structured Programming with go to Statements中,文章分析了许多常见编程任务,然后发现其中的一些使用GOTO将得到最理想的结构。

限制GOTO

许多语言,如 C 语言和 Java,提供了相关的控制流语句,如 break 和 continue,它们都是有效地被限制的 goto 语句。它们的作用是无条件跳转,但是只能够跳到循环块结束的位置 —— 继续进入下一循环(continue)或者结束循环(break)。

switch/case结构

C 语言、C++ 和 Java 中的 switch 语句高效地实现了一个多路 goto,跳转目标由表达式的值来选择。这也导致了我们没有不得不使用 goto 的理由。

针对这些,导致目前 goto 的使用情况是这样的:goto 语句的结果在C/C++等高级编程语言中保留了goto语句,但被建议不用或少用。

在一些更新的高级编程语言,如 Java 不提供 goto 语句,它虽然指定 goto 作为关键字,但不支持它的使 用,使程序简洁易读;尽管如此后来的 c# 还是支持 goto 语句的,goto 语句一个好处就是可以保证程序存在唯一的出口,避免了过于庞大的 if 嵌套。

另一方面,goto 语句只是不提倡,当然不是禁用,那么在什么情况下可以使用 goto 语句呢

可以考虑使用 goto 的情形:

· 从多重循环中直接跳出 ;

· 出错时清除资源;

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

不加限制地使用 goto:破坏了清晰的程序结构,使程序的可读性变差,甚至成为不可维护的"面条代码"。

经常带来错误或隐患,比如它可能跳过了某些对象的构造、变量的初始化、重要的计算等语句。

下列关于使用 goto 语句的原则可以供读者参考。

1. 使用 goto 语句只能 goto 到同一函数内,而不能从一个函数里 goto 到另外一个函数里。

2. 使用 goto 语句在同一函数内进行 goto 时,goto 的起点应是函数内一段小功能的结束处,goto 的目的 label 处应是函数内另外一段小功能的开始处。

3. 不能从一段复杂的执行状态中的位置 goto 到另外一个位置,比如,从多重嵌套的循环判断中跳出去就是不允许的。

4. 应该避免像两个方向跳转。这样最容易导致"面条代码"。

阅读过 linux 内核代码的同学应该注意到,linux 内核代码里面其实有不少地方用了 goto 语句,

这是在/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;}

但是你会发现,这些地方的goto语句,使用非常谨慎,基本都遵循上面提到的几个原则。

本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。

文章来源于:电子产品世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    用函数控制流程 2 使用FOR(;;)或While(1) 如果goto语句已经过时,那么对程序创建无限循环应该如何去做呢,这是一些硬件工程师可能会疑惑的问题。毕竟,之前都是通过创建一个goto语句......
     to vote! 为什么它这么不受待见? 二十几年前,当计算机编程尚处于起步阶段时,程序流程是由 “GOTO” 语句来控制。该类语句允许程序员对当前代码行断行,而直接进入另一个不同的代码段。 下图......
    将介绍初学者必须掌握的基本运算指令,如加法、减法、乘法、除法等。通过实例讲解和代码演示,让你快速掌握这些指令的使用方法,为后续学习打下坚实基础。 7、初学PKC编程必会代码运算指令(建议......
    对于门访问安全因此,我们打算通过引进一个电子密码锁系统,该系统包括一个人得到一个访问某些项目之前要输入密码的安全性,以及在家里,一个房间密码锁系统,不只是普通的单用户密码锁系统,需要用户插入已编程......
    STM32指针抽象出I2C的数据实例;1.写在前面 I2C总线是由PHILIPS公司开发的一种简单、「双向二线制同步串行总线」。 关于i2c的使用,并不陌生,STM32、C51、ARM......
    西门子SCL的使用区间(Region)编程实例;功能 在 SCL 中,可在区间内构建程序代码。由于集成了相关程序段而且可根据需要对区间进行灵活展开和折叠,因而程序代码更为清晰直观。在区......
    misc设备驱动模型及实例解析;1、misc设备驱动模型       本节我们来看一下misc设备驱动模型的有关内容,首先是看看它的设备结构体,定义在include/linux......
    基于tiny4412的Linux內核移植 --- 实例学习中断背后的知识(2);平台 tiny4412 ADK Linux-4.9   概述 前面一篇博文基於tiny4412的Linux內核......
    数控切割机和激光切割机的区别 数控切割机编程入门;  数控切割机和激光切割机的区别   数控切割机和激光切割机是两种不同的切割工具,它们的区别在以下几个方面:   原理不同:数控......
    、键盘矩阵电路、驱动器和红外发光二极管组成,遥控信号为37.9 kHz的脉冲载波被遥控编码脉冲调制的已调波,如图1所示。 遥控编码脉冲由引导码、用户码、功能码和功能码的相反码组成,用户......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>