关于C语言的goto语句存在很多争议,很多书籍都建议“谨慎使用,或者根本不用”。Linux之父Linus在Linux中大量使用goto,也是在启示着我们可以合理使用goto语句。

存在即合理,既然是C语言中的一个知识点,我们还是有必要学会使用。先看一些goto如何用:

一、goto的基本语法

goto语句有两部分:goto和标签名。标签的命名规则与变量的命名规则一样。如:

goto label;

要让这条语句正常工作,函数还必须包含另一条标为label的语句,该语句以标签名后紧跟一个冒号开始,如:

label:printf("goto here.\n");

二、goto的例子

/*
编译环境:mingw32  gcc6.3.0
*/
#include <stdio.h>
#include <stdlib.h>/* 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用法,可以跳出多重循环,程序执行过程中遇到goto语句就可以跳转到label处继续执行。

值得注意的一点是:goto语句与其跳转的标签处必须在同一个函数内。

三、goto与break、continue的区别?

同样是跳转语句,goto语句与break、continue语句有什么区别呢?

实际上,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循环 */}printf("%s : i = %d\n", __FUNCTION__, i);}printf("Now i = %d\n", i);break;         /* 第一个break:跳出while循环 */  }printf("test break end!");
}

运行结果:

从运行结果我们明显可以知道,break可以退出当前循环。

在本例子中,第一个break语句退出当前的for循环,第二个break语句退出当前的while循环。可见,一个break可退出一层循环。

所以,根据break与goto的特点知道,如果是跳出很多层循环,使用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:结束本次循环(而不是终止这一层循环)继续进入下一次循环 */}printf("%s : i = %d\n", __FUNCTION__, i);}printf("test break end!");
}

运行结果:

从运行结果我们明显可以知道,continue可以结束本次循环(而不是整个循环)而进入下一次循环(i所代表的就是循环的次数)。

四、支持与反对goto的理由是什么?

1、不提倡使用goto

不提倡使用goto的占比应该比较多,不提倡的原因主要是:很容易把逻辑弄乱且难以理解。

2、使用goto的理由

这一部分人认为goto可以用在以下两种情况比较方便:

(1)跳出多层循环。

这个例子就类似于我们上面的goto测试程序。

(2)异常处理。

一个函数的执行过程可能会产生很多种情况异常情况。下面有几种处理方式,以代码为例:

方法一:做出判断后,如果条件出错,直接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;
}

其中,方法三就是很多人都提倡的方式。统一用 goto err 跳转是最方便且效率最高的,从反汇编语句条数可以看出指令用的最少,消耗的寄存器也最少,效率无疑是最高的。

并且,使用goto可以使程序变得更加可扩展。当程序需要在错误处理时释放资源时,统一到goto处理最方便。这也是为什么很多大型项目,开源项目,包括Linux,都会大量的出现goto来处理错误!

以上就是关于goto语句的基本使用、goto与break、continue的区别的总结,如有错误,欢迎指出!如果觉得不错可以帮忙分享~

参考资料:

1、《C Primer Plus》
2、https://www.cnblogs.com/trying/archive/2012/06/25/2863753.html

扫码或长按关注

回复「 加群 」进入技术群聊

为什么Linux内核里大量使用goto,而很多书籍却不提倡使用?相关推荐

  1. Linux 内核里的“智能指针”【转】

    转自:http://blog.jobbole.com/88279/ 众所周知,C/C++语言本身并不支持垃圾回收机制,虽然语言本身具有极高的灵活性,但是当遇到大型的项目时,繁琐的内存管理往往让人痛苦异 ...

  2. Linux 内核里的“智能指针”

    Linux 内核里的"智能指针" from: http://begeek.cn/post/7889.html?ref=myread 众所周知,C/C++语言本身并不支持垃圾回收机制 ...

  3. Linux内核里的“智能指针” (续)

    在上一篇文章<Linux内核里的智能指针>里介绍了Linux内核如何使用引用计数来更加安全的管理内存,本文承接前篇,主要介绍几点使用kref时的注意事项. Linux内核文档kref.tx ...

  4. exfat单元分配要设置多少_微软宣布,支持往Linux内核里添加exFAT存储了!跨系统存储的福音...

    栗子 发自 凹非寺  量子位 报道 | 公众号 QbitAI exFAT,是微软开发的文件系统,为闪存而生. 你的U盘.SD卡.手机等等存储设备,能存4G以上的大文件,很大程度上是它的功劳. 可exF ...

  5. linux红黑树节点没有数据,真正理解红黑树,真正的(Linux内核里大量用到的数据 -电脑资料...

    作为一种数据结构,红黑树可谓不算朴素,因为各种宣传让它过于神秘,网上搜罗了一大堆的关于红黑树的文章,不外乎千篇一律,介绍概念,分析性能,贴上代码,然后给上罪恶的一句话,它最坏情况怎么怎么地... 1. ...

  6. Linux 内核里的数据结构——基数树

    Linux 内核里的数据结构--基数树 正如你所知道的,Linux内核提供了许多不同的库和函数,它们实现了不同的数据结构和算法.在这部分,我们将研究其中一种数据结构--基数树Radix tree.在 ...

  7. linux5关闭apic服务,阐述Linux内核里面的APIC编程

    微软操作系统的火热,你是在应用Linux操作系统么?如果你是Linux操作系统的老用户. 这里为你讲解的问题会对Linux内核里面的APIC编程有所帮助.Linux内核的名字也是"Linux ...

  8. Linux内核中段伪例,利用Linux内核里的Use-After-Free(UAF)漏洞提权

    *本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担. * 作者:nickchang 上个月爆出的CVE-2016-0728 (http: ...

  9. 华人学者往Linux内核里提交bug,社区把整个明尼苏达大学拉黑了

    梦晨 萧箫 发自 凹非寺 量子位 报道 | 公众号 QbitAI Linux内核的维护者Greg K-H,突然把整个明尼苏达大学拉黑了! 这是咋回事? 原来明尼苏达大学华人教授K.J Lu带领的团队在 ...

最新文章

  1. 从NCBI当中SRA数据库中下载高通量测序数据
  2. 编写你的第一个 Flutter App
  3. Python基础04 运算
  4. ZOJ 3633 rmq 重点在于转化
  5. canal —— 阿里巴巴mysql数据库binlog的增量订阅消费组件
  6. QT打印窗口、退出、设置字体及颜色、设置时间、控件实现系统函数、添加资源文件(菜单图片)、工具栏添加图片
  7. jquery load 事件用法
  8. C# 托管资源与非托管资源
  9. Android Studio(7)---从模板添加代码
  10. Oracle数据库脚本学习:建用户、删用户、建表、改表、删表
  11. python输出函数是什么_Python中打印函数使用概述,python,print,用法,总结
  12. 《史蒂夫·乔布斯传》PDF下载
  13. utools插件合集 v1.3.5绿色版
  14. 气血瘀滞热入血室闭经案
  15. 安卓 Day 23 :利用视图翻页器实现引导项
  16. 三月的雨季给我带来了希望
  17. C++/java设计模式汇总
  18. EasyNVR查看直播视频流显示黑屏原因排查
  19. Globalsign和Symantec SSL证书哪家好
  20. 快读快写和fread,fwrite--zhengjun

热门文章

  1. VARIANT变体类型数据
  2. 张左峰的歪理邪说 之 大话Redmine插件
  3. 在批处理文件中启动MediaPlayer播放制定文件
  4. 用VSTS进行网站压力测试
  5. vmware linux
  6. pyecharts对于经纬度_一文带你掌握Pyecharts地理数据可视化的方法
  7. Python 第三方库之 docxtpl (处理word文档)
  8. 深度学习之卷积神经网络(Convolutional Neural Networks, CNN)
  9. 几何分布的期望和方差公式推导_超几何分布的数学期望与方差推导
  10. openjdk:8u22-jre-alpine在java开发中的NullPointerException错误解决方案