goto的理解与使用

26 篇文章 2 订阅
7 篇文章 0 订阅

Goto

记得学C语言时,老师就有讲过:"不要使用goto, 这是一个坏习惯,而且很危险!"各类书籍上也是这么说,所以之前写的代码几乎从来没有使用过goto。
现在工作在搞Linux硬件驱动,内核源码里却有大量goto,看了些论坛大神的讨论,确实goto不应该多用,不然逻辑会搞得混乱。
但是自己也得会,不然内核代码也是看的稀里糊涂。

功能:

goto语句可以使程序在没有任何条件的情况下跳转到指定的位置。

直接上我的测试代码。
gototest.c

#include <stdio.h>
int main(void){
    char a;
cycle:
    printf("test goto\n");
    while(scanf(" %c",&a)){
        if('i' == a){
            printf("a = %d\n",a);
            goto in;
        }
        else if('c' == a){
            goto cycle;
        }
        else {
            printf("a = %d\n",a);
            goto out;
        }
   }
in:
printf("label_in!\n");

out:
printf("label_out!\n");

return 0;
}

测试:

hezaizai@ubuntu:~/code_test$ gcc gototest.c -o goto

hezaizai@ubuntu:~/code_test$ ./goto
test goto
i
a = 105
label_in!
label_out!
hezaizai@ubuntu:~/code_test$ ./goto
test goto
o
a = 111
label_out!
hezaizai@ubuntu:~/code_test$ ./goto
test goto
c
test goto
c
test goto
c
test goto
c
test goto
c
test goto
c
test goto
b
a = 98
label_out!

说明

1、输入i,goto in
2、输入o,goto out
3、输入c,goto cycle
4、如果goto了in,后面的out也一定会执行。换句话说,程序无论以哪种方式执行完毕都会执行out:。

PS

如果你够仔细,会发现在代码里while(scanf(" %c",&a)) %c之前有个空格。
为什么要这个空格呢?
复制我的代码,分别加和不加空格试下。
不卖关子了,是因为scanf语句吃掉回车或者空格,如果不加的话,循环是无效的。
建议还是跑下代码,感受下goto,和scanf()。

内核源码展示

static int omap3_l3_probe(struct platform_device *pdev)
{
	struct omap3_l3 *l3;
	struct resource *res;
	int ret;

	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
	if (!l3)
		return -ENOMEM;

	platform_set_drvdata(pdev, l3);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "couldn't find resource\n");
		ret = -ENODEV;
		goto err0;
	}
	l3->rt = ioremap(res->start, resource_size(res));
	if (!l3->rt) {
		dev_err(&pdev->dev, "ioremap failed\n");
		ret = -ENOMEM;
		goto err0;
	}

	l3->debug_irq = platform_get_irq(pdev, 0);
	ret = request_irq(l3->debug_irq, omap3_l3_app_irq, IRQF_TRIGGER_RISING,
			  "l3-debug-irq", l3);
	if (ret) {
		dev_err(&pdev->dev, "couldn't request debug irq\n");
		goto err1;
	}

	l3->app_irq = platform_get_irq(pdev, 1);
	ret = request_irq(l3->app_irq, omap3_l3_app_irq, IRQF_TRIGGER_RISING,
			  "l3-app-irq", l3);
	if (ret) {
		dev_err(&pdev->dev, "couldn't request app irq\n");
		goto err2;
	}

	return 0;

err2:
	free_irq(l3->debug_irq, l3);
err1:
	iounmap(l3->rt);
err0:
	kfree(l3);
	return ret;
}

内核中一般使用goto来处理错误,也是有逻辑顺序的,上述代码如果正常不出错执行完,最后会依次执行err2、err1、err0标签里的代码。
自己可以顺着代码体会下。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用goto语句跳转到switch语句中的某个case标签或if语句中的某个标签,但是这种做法容易导致程序的可读性和可维护性降低,不建议使用。更好的做法是使用函数或者重构代码来避免使用goto语句。 ### 回答2: goto、if和switch可以结合使用来实现特定的控制流程。通过条件判断和跳转语句,可以实现程序在不同条件下的不同执行路径。 在结合使用时,一般的做法是在if或switch语句中使用goto跳转到标签位置,以实现特定的流程控制。 例如,在某个函数中,我们有多个条件需要判断并执行不同的操作。可以先使用if或switch语句进行条件判断,然后在符合条件的情况下,通过goto语句跳转到具体的标签位置。 示例代码如下: if (条件1) { // 执行操作1 goto 标签1; } else if (条件2) { // 执行操作2 goto 标签2; } else if (条件3) { // 执行操作3 goto 标签3; } 标签1: // 操作1后的代码 标签2: // 操作2后的代码 标签3: // 操作3后的代码 在上述示例中,根据不同的条件,程序会跳转到对应的标签位置执行相应的操作。通过结合使用if、switch和goto,我们可以实现复杂的逻辑流程控制。 需要注意的是,goto语句具有一定的风险,如果使用不当可能会导致程序流程混乱,使代码变得难以理解和维护。因此,在使用goto语句时,应慎重考虑,并确保代码的逻辑和可读性。 ### 回答3: 在某些编程语言中,可以将goto、if和switch结合使用来实现特定的控制流程。下面是一种可能的方法: 首先,将程序的逻辑按照顺序划分为多个小块。每个小块可能对应一个特定的功能或条件。 在每个小块的开始处使用if或switch语句进行条件判断。if语句可以根据条件的真假执行不同的代码块,而switch语句可以根据不同的条件值选择不同的代码块。 对于需要跳转到其他代码块继续执行的情况,可以使用goto语句。在需要跳转的地方使用标签标记,在goto语句中指定要跳转到的标签。这样程序就可以跳转到指定标签处继续执行后续的代码。 需要注意的是,滥用goto语句可能导致代码难以理解、调试和维护。因此,建议在编写代码时尽量避免使用goto语句,而是尽量使用结构化的控制流程语句如if和switch来处理条件判断。只有在极端情况下,或者在必要的情况下,才考虑使用goto语句。 综上所述,goto、if和switch可以组合使用来实现在特定条件下跳转到其他代码块继续执行的控制流程。但在实际编程中,应尽量避免滥用goto语句,而是使用结构化的控制流程语句来处理条件判断。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值