记得学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:。
如果你够仔细,会发现在代码里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标签里的代码。
自己可以顺着代码体会下。