管理C程序资源的最佳方法是什么?是使用嵌套的if结构还是使用goto语句?
我知道有很多关于goto语句的禁忌。不过,我认为本地资源的清理是有道理的。我提供了两个样品。一个比较嵌套的if结构,另一个使用goto语句。我个人认为goto语句可以使代码更容易阅读。对于那些可能认为嵌套if提示结构更好的人来说,想象一下如果数据类型不是char*,比如句柄。我觉得嵌套的if结构将失去对一系列CreateFile函数或任何其他需要大量参数的函数的控制。
这个文章演示了本地goto语句为C代码创建RAII。代码很整洁,易于遵循。假设这是一系列嵌套的if语句。
我理解goto在许多其他语言中是禁忌的,因为它们存在其他控制机制,如try/等,但是在C语言中似乎是合适的。
#include <stdlib.h>
#define STRING_MAX 10
void gotoExample()
{
char *string1, *string2, *string3, *string4, *string5;
if ( !(string1 = (char*) calloc(STRING_MAX, sizeof(char))) )
goto gotoExample_string1;
if ( !(string2 = (char*) calloc(STRING_MAX, sizeof(char))) )
goto gotoExample_string2;
if ( !(string3 = (char*) calloc(STRING_MAX, sizeof(char))) )
goto gotoExample_string3;
if ( !(string4 = (char*) calloc(STRING_MAX, sizeof(char))) )
goto gotoExample_string4;
if ( !(string5 = (char*) calloc(STRING_MAX, sizeof(char))) )
goto gotoExample_string5;
//important code goes here
gotoExample_string5:
free(string4);
gotoExample_string4:
free(string3);
gotoExample_string3:
free(string2);
gotoExample_string2:
free(string1);
gotoExample_string1:
}
void nestedIfExample()
{
char *string1, *string2, *string3, *string4, *string5;
if (string1 = (char*) calloc(STRING_MAX, sizeof(char)))
{
if (string2 = (char*) calloc(STRING_MAX, sizeof(char)))
{
if (string3 = (char*) calloc(STRING_MAX, sizeof(char)))
{
if (string4 = (char*) calloc(STRING_MAX, sizeof(char)))
{
if (string5 = (char*) calloc(STRING_MAX, sizeof(char)))
{
//important code here
free(string5);
}
free(string4);
}
free(string3);
}
free(string2);
}
free(string1);
}
}
int main(int argc, char* argv[])
{
nestedIfExample();
gotoExample();
return 0;
}我还想引用Linux关于Linux语句的话。
有时结构是不好的,并进入了道路,而使用一个"goto“就更清楚了。 例如,有不嵌套的条件是很常见的。 在这种情况下,您有两种可能性
Pascal语言是后一个问题的一个主要例子。因为它没有“中断”语句,所以循环在(传统的) Pascal中常常看起来像完全的狗屎,因为你必须添加完全任意的逻辑才能说“我现在就完了”。
goto是否可用于资源管理?我应该使用嵌套的if语句还是有更好的方法?
更新: C语言中的Gotos示例
发布于 2010-11-10 20:51:15
使用goto进行清理有一个优点,即它不太容易出错。必须释放在每个返回点上分配的每一个资源,可能会导致某一天在进行维护工作时缺少一些清理。
尽管如此,我将引用Knuth的“带有goto语句的结构化编程”:
我主张在某些情况下取消go to's,并在其他情况下引入它们。
Knuth在同一篇论文中引用了Dijkstra的话:
“请不要落入这样的陷阱,以为我对陈述非常固执。我有一种不舒服的感觉,认为别人在用它来做宗教,就好像编程的概念问题可以通过一个简单的编码规则来解决似的!”29。
发布于 2010-11-10 20:51:44
如果通过使用goto可以避免编写复杂的代码,那么就使用goto。
您的示例也可以这样编写(没有goto):
void anotherExample()
{
char *string1, *string2, *string3, *string4, *string5;
string1 = string2 = string3 = string4 = string5 = 0;
if ((string1 = (char*) calloc(STRING_MAX, sizeof(char)))
&& (string2 = (char*) calloc(STRING_MAX, sizeof(char)))
&& (string3 = (char*) calloc(STRING_MAX, sizeof(char)))
&& (string4 = (char*) calloc(STRING_MAX, sizeof(char)))
&& (string5 = (char*) calloc(STRING_MAX, sizeof(char))))
{
//important code here
}
free(string1);
free(string2);
free(string3);
free(string4);
free(string5);
}发布于 2010-11-10 21:14:42
毫无疑问,Dijkstra是编程界的一位令人敬畏的人物。他的后藤认为有害论文被夸大了。是的,GoTo可能被不加区分地使用,而且可能有害,但许多人认为完全禁止GoTo是没有道理的。Knuth给Dijkstra提供了一个非常合理的反驳:用GO TOs进行结构化编程。
阅读Knuth的文章,您会发现您的GoTo模式是GoTo的一个很好的用途。
顺便说一句,Dijkstra对于许多其他的事情也很适用。不如:
迪克斯特拉是一位伟大的数学家,为计算机科学做出了巨大贡献。然而,我不认为他必须处理,或感兴趣的,日复一日的东西,我们的节目99.99 %。
只在合理和结构上使用GoTo。很少用。但一定要用它们。
https://stackoverflow.com/questions/4148838
复制相似问题