c语言goto是标识符吗,这是C语言中goto的一个不错的用例吗?

linux样式指南提供了使用goto的具体原因,这些与您的示例一致:

使用gotos的基本原理是:

无条件陈述更易于理解和遵循

嵌套减少

防止在进行修改时不更新单个出口点而导致错误

节省了编译器的工作,以优化冗余代码;)

免责声明我不应该分享我的工作。这里的示例有些虚构,请耐心接受。

这对内存管理很有用。我最近研究了动态分配内存的代码(例如char *,函数返回的代码)。该函数查看路径并通过解析路径的令牌来确定路径是否有效:

tmp_string=strdup(string);token=strtok(tmp_string,delim);while(token!=NULL){...some statements,some involving dynamically allocated memory...if(check_this()){free(var1);free(var2);...free(varN);return1;}...some more stuff...if(something()){if(check_that()){free(var1);free(var2);...free(varN);return1;}else{free(var1);free(var2);...free(varN);return0;}}token=strtok(NULL,delim);}free(var1);free(var2);...free(varN);return1;

现在对我来说,如果您需要添加以下代码,则以下代码会更好,更易于维护varNplus1:

intretval=1;tmp_string=strdup(string);token=strtok(tmp_string,delim);while(token!=NULL){...some statements,some involving dynamically allocated memory...if(check_this()){retval=1;gotoout_free;}...some more stuff...if(something()){if(check_that()){retval=1;gotoout_free;}else{retval=0;gotoout_free;}}token=strtok(NULL,delim);}out_free:free(var1);free(var2);...free(varN);returnretval;

现在,代码还存在其他各种问题,即N大于10,并且该函数超过450行,并且在某些地方具有10级嵌套。

但是我提供了我的主管来重构它,我做到了,现在它是一堆都很短的函数,而且它们都具有linux风格

intfunction(constchar*param){intretval=1;char*var1=fcn_that_returns_dynamically_allocated_string(param);if(var1==NULL){retval=0;gotoout;}if(isValid(var1)){retval=some_function(var1);gotoout_free;}if(isGood(var1)){retval=0;gotoout_free;}out_free:free(var1);out:returnretval;}

如果考虑不带gotos 的等效项:

intfunction(constchar*param){intretval=1;char*var1=fcn_that_returns_dynamically_allocated_string(param);if(var1!=NULL){if(isValid(var1)){retval=some_function(var1);}else{if(isGood(var1)){retval=0;}}free(var1);}else{retval=0;}returnretval;}

对我而言,在第一种情况下,很明显,如果第一个函数返回NULL,则我们不在这里,而在返回0。在第二种情况下,我必须向下滚动才能看到if包含整个函数。授予第一个在样式上向我指示此名称(名称“ out”),第二个在语法上进行指示。第一个更加明显。

另外,我非常喜欢free()在函数末尾使用语句。部分原因是,根据我的经验,free()函数中间的语句很难闻,并向我表明我应该创建一个子例程。在这种情况下,我var1在函数中创建了函数,但无法free()在子例程中创建它,但这就是为什么goto out_freegoto out样式如此实用的原因。

我认为程序员必须长大,认为这goto是邪恶的。然后,当他们足够成熟时,他们应该浏览Linux源代码并阅读linux样式指南。

我应该补充一点,我非常一致地使用这种样式,每个函数都有一个int retval,一个out_free标签和一个out标签。由于风格上的一致性,提高了可读性。

奖励:打破并继续

假设您有一个while循环

char*var1,*var2;charline[MAX_LINE_LENGTH];while(sscanf(line,...){var1=functionA(line,count);var2=functionB(line,count);if(functionC(var1,var2){count++continue;}...a bunch of statements...count++;free(var1);free(var2);}

这段代码还有其他问题,但是一件事是continue语句。我想重写整个内容,但是我的任务是以较小的方式对其进行修改。以一种令我满意的方式来重构它可能需要几天的时间,但实际的更改大约需要花半天的时间。问题在于,即使continue我们仍然需要自由var1和自由var2。我必须添加一个var3,这让我想不得不镜像free()语句。

当时我是一个相对较新的实习生,但是前一段时间我一直在看linux源代码,所以我问我的主管我是否可以使用goto语句。他说可以,而我做到了:

char*var1,*var2;charline[MAX_LINE_LENGTH];while(sscanf(line,...){var1=functionA(line,count);var2=functionB(line,count);var3=newFunction(line,count);if(functionC(var1,var2){gotonext;}...a bunch of statements...next:count++;free(var1);free(var2);}

我认为继续充其量是可以的,但对我而言,它们就像带有隐形标签的goto。休息时间也一样。我仍然希望继续或中断,除非像这里的情况那样,它迫使您在多个位置镜像修改。

我还要补充一点,goto next;和的使用next:对我来说并不令人满意。它们仅比镜像free()的和count++语句更好。

goto几乎总是错误的,但是必须知道何时可以使用它们。

我没有讨论的一件事是错误处理,该问题已被其他答案所涵盖。

性能

#include#includechar*strtok(s,delim)registerchar*s;registerconstchar*delim;{registerchar*spanp;registerintc,sc;char*tok;staticchar*last;if(s==NULL&&(s=last)==NULL)return(NULL);/** Skip (span) leading delimiters (s += strspn(s, delim), sort of).*/cont:c=*s++;for(spanp=(char*)delim;(sc=*spanp++)!=0;){if(c==sc)gotocont;}if(c==0){/* no non-delimiter characters */last=NULL;return(NULL);}tok=s-1;/** Scan token (scan for delimiters: s += strcspn(s, delim), sort of).* Note that delim must have one NUL; we stop if we see that, too.*/for(;;){c=*s++;spanp=(char*)delim;do{if((sc=*spanp++)==c){if(c==0)s=NULL;elses[-1]=0;last=s;return(tok);}}while(sc!=0);}/* NOTREACHED */}

如果我错了,请指正我,但我相信cont:标签和goto cont;语句的存在是为了提高性能(它们肯定不会使代码更具可读性)。通过执行以下操作,可以将其替换为可读代码

while(isDelim(*s++,delim));

跳过定界符。但是为了尽可能快并避免不必要的函数调用,他们是这样做的。

我读了Dijkstra的论文,发现它很深奥。

google“ dijkstra goto声明被认为是有害的”,因为我没有足够的声誉来发布两个以上的链接。

我已经看到它被引用为不使用goto的原因,并且阅读它对我对goto的使用没有任何改变。

附录:

在考虑所有有关持续和中断的问题时,我想出了一条整洁的规则。

如果在while循环中有一个continue,则while循环的主体应该是一个函数,而continue应该是一个return语句。

如果在while循环中有一个break语句,则while循环本身应该是一个函数,而break应该成为return语句。

如果两者都存在,则可能出了问题。

由于范围问题,这并不总是可能的,但是我发现这样做可以使我的代码推理变得容易得多。我注意到,只要while循环中断或继续,都会给我一种不好的感觉。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值