编程小技巧

    返回首页    发表留言
本文作者:李德强
          技巧七:合理使用goto语句
 
 

        goto语句又称为无条件转移语句,使用goto语句可以使CPU直接跳转到其label标注处执行程序。但是在多数的高级编程语言课程上都不提倡使用goto语句,原因是goto语句过于灵活,过度的使用可能会导致结构化设计程序的逻辑混乱以及降低代码可读性。我在刚刚走出大学参加工作时,也对goto语句畏如蛇蝎,编程时宁可让多写很多代码也要避免使用goto语句。然而在自己不断的学习和积累经验的过程中,我常常会看到很多优秀的编程人员在使用goto语句,而且大名鼎鼎的Linux内核中有大量的goto语句,并且Linus本人也推荐合理的使用goto语句。注意,这里说的是合理的使用goto会大大简化代码,并且使程序逻辑更加清晰。

        伟大的哲学家黑格尔说过:存在即合理。我们先来看看这样的一个多层循环嵌套的例子:

int found = 0;
for (int i = 0; i < n && !found; i++)
{
        for (j = 0; j < m && !found; j++)
        {
                if (a[i] == b[j])
                {
                        found = 1;
                }
        }
}
if (found)
{
        //do something
}

        在上面程序中,的判断和跳出过程有些复杂。在每一个for语句的循环条件判断中都要加上一个 !found 表达式来判断是否已经找到a和b的相同值,如果找到则结束循环。我们再来看看使用goto语句的程序:

for (int i = 0; i < n; i++)
{
        for (j = 0; j < m; j++)
        {
                if (a[i] == b[j])
                {
                        goto found;
                }
        }
}
found:
        // do something

        可以看到使用了goto语句后,程序逻辑变得清晰简洁。当然在很多高级语言中已经避免了这个问题,比如在Java中有break label;语句来完成这个功能,但是请大家注意,这个语法跟goto label;如此的相似,其实就是goto label的变种。

        我们再来看看另外的例子我们在做一些内存申请时要对申请的结果做判断,如果申请内存失败则释放之前已经申请过的内存空间:

void* p0 = malloc(MAX_SIZE * sizeof(char));
if(p0 == NULL)
{
        return -1;
}

void* p1 = malloc(MAX_SIZE * sizeof(char));
if(p1 == NULL)
{
        free(p0);
        return -1;
}

void* p2 = malloc(MAX_SIZE * sizeof(char));
if(p2 == NULL)
{
        free(p1);
        free(p0);
        return -1;
}

void* p3 = malloc(MAX_SIZE * sizeof(char));
if(p3 == NULL)
{
        free(p2);
        free(p1);
        free(p0);
        return -1;
}

        可以看到,代码中如果申请内存的功能写的越多,代码就会变的越复杂、越啰唆。我们再来看看使用了goto语句后的程序:

void* p0 = malloc(MAX_SIZE * sizeof(char));
if (p0 == NULL)
{
        goto _free_p0;
}

void* p1 = malloc(MAX_SIZE * sizeof(char));
if (p1 == NULL)
{
        goto _free_p1;
}

void* p2 = malloc(MAX_SIZE * sizeof(char));
if (p2 == NULL)
{
        goto _free_p2;
}

void* p3 = malloc(MAX_SIZE * sizeof(char));
if (p3 == NULL)
{
        goto _free_p3;
}

// do something

_free_p3:
        free(p3);
_free_p2:
        free(p2);
_free_p1:
        free(p1);
_free_p0:
        free(p0);

        使用了goto语句后程序不但没有变复杂,反而变的更加简洁清晰了。

        另外在一些特殊情况下巧妙的使用goto语句还可以达到循环的目的,或是异常处理逻辑等等。这些小技巧请读者自己思考。

 

        今天的小技巧你学会了吗?

 

 

    返回首页    返回顶部
  看不清?点击刷新

 

  Copyright © 2015-2023 问渠网 辽ICP备15013245号