管理C程序资源的最佳方式是什么? 我应该使用嵌套的if结构还是应该使用goto语句?
我知道有很多关于goto语句的禁忌 。 不过,我认为这对于本地资源清理是合理的。 我提供了两个样本。 比较一个嵌套的if结构和另一个使用goto语句。 我个人发现goto语句使代码更易于阅读。 对于那些可能争论嵌套if提示更好的结构,想象一下,如果数据类型是char *以外的其他东西,就像Windows句柄。 我觉得嵌套的if结构会与一系列CreateFile函数或任何其他需要大量参数的函数失去联系。
本文演示了本地goto语句为C代码创建RAII。 代码很整洁,很容易遵循。 想象一下,作为一系列嵌套的if语句。
我明白goto在许多其他语言中是禁忌的,因为它们存在像try / catch等其他控制机制,但是,在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; }我还想引用Linus Torvalds关于Linux 内核中的 goto语句。
有时候结构不好 ,并且会阻碍,并且使用“goto”更加清晰。
例如,有条件的不常见是很常见的。
在这种情况下,你有两种可能性
使用goto,并且很高兴,因为它不强制嵌套
这使得代码更具可读性,因为代码只是执行算法所要做的事情。
复制代码,并将其重写为嵌套形式,以便可以 使用结构化的跳转。
这通常会使代码更容易读取,难以维护,而且更大。
帕斯卡语言是后一个问题的主要例子。 因为它没有“break”语句,所以(传统的)Pascal中的循环往往看起来像完全的狗屎,因为你必须添加完全任意的逻辑来说“我现在完成了”。
是否可以接受资源管理? 我应该使用嵌套if语句还是有更好的方法?
更新: 在C中的好Gotos的例子
What is the best way to manage resources for a C program. Should I use a nested if structure or should I use goto statements?
I am aware there is a lot of taboo about goto statements. However, I think it is justified for local resource clean up. I have supplied two samples. One compares a nested if structure and another uses goto statements. I personally find the goto statements make the code easier to read. For those who might argue that the nested if prompt better structure, imagine if the datatype was something other than a char*, like a Windows handle. I feel that the nested if structure would get out of hand with a series of CreateFile functions or any other function that takes large quantities of parameters.
This article demonstrates that local goto statements create RAII for C code. The code is neat an easy to follow. Imagine that as a series of nested if statements.
I understand that goto is taboo in many other languages because their exists other control mechanisms like try/catch etc, however, in C it seems appropriate.
#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; }I would also like to quote Linus Torvalds on goto statements inside the Linux Kernel.
And sometimes structure is bad, and gets into the way, and using a "goto" is just much clearer.
For example, it is quite common to have conditionals THAT DO NOT NEST.
In which case you have two possibilities
use goto, and be happy, since it doesn't enforce nesting
This makes the code more readable, since the code just does what the algorithm says it should do.
duplicate the code, and rewrite it in a nesting form so that you can use the structured jumps.
This often makes the code much LESS readable, harder to maintain, and bigger.
The Pascal language is a prime example of the latter problem. Because it doesn't have a "break" statement, loops in (traditional) Pascal end up often looking like total shit, because you have to add totally arbitrary logic to say "I'm done now".
Is goto acceptable for resource management? Should I use nested if statements or is there a better way?
Update: Examples of Good Gotos In C
最满意答案
使用goto进行清理的好处是不易出错。 不得不释放每个和每个返回点上分配的每个资源,这可能会导致某人某天在执行维护工作时缺少一些清理工作。
也就是说,我会引用Knuth的“结构化编程与转换语句”:
我主张在某些情况下取消转入,并在其他情况下引入。
和Knuth在同一篇论文中对Dijkstra的引用:
“请不要陷入相信我对于[去声明]我非常干涉的陷阱中,我有这样的不舒服的感觉,即其他人正在从中获得宗教信仰,好像编程的概念问题可以通过解决一个简单的编码技巧!“ [29]。
Cleanup using goto has the advantage that it's less error-prone. Having to free each and every resource allocated on each and every return point can lead to someone someday missing some cleanup when doing maintenance work.
That said, I'll quote Knuth's "Structured Programming with goto Statements":
I argue for the elimination of go to's in certain cases, and for their introduction in others.
and Knuth's quote of Dijkstra in that same paper:
C:嵌套Ifs或Gotos(C: Nested Ifs or Gotos)"Please don't fall into the trap of believing that I am terribly dogmatical about [the go to statement]. I have the uncomfortable feeling that others are making a religion out of it, as if the conceptual problems of programming could be solved by a single trick, by a simple form of coding discipline!" [29].
管理C程序资源的最佳方式是什么? 我应该使用嵌套的if结构还是应该使用goto语句?
我知道有很多关于goto语句的禁忌 。 不过,我认为这对于本地资源清理是合理的。 我提供了两个样本。 比较一个嵌套的if结构和另一个使用goto语句。 我个人发现goto语句使代码更易于阅读。 对于那些可能争论嵌套if提示更好的结构,想象一下,如果数据类型是char *以外的其他东西,就像Windows句柄。 我觉得嵌套的if结构会与一系列CreateFile函数或任何其他需要大量参数的函数失去联系。
本文演示了本地goto语句为C代码创建RAII。 代码很整洁,很容易遵循。 想象一下,作为一系列嵌套的if语句。
我明白goto在许多其他语言中是禁忌的,因为它们存在像try / catch等其他控制机制,但是,在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; }我还想引用Linus Torvalds关于Linux 内核中的 goto语句。
有时候结构不好 ,并且会阻碍,并且使用“goto”更加清晰。
例如,有条件的不常见是很常见的。
在这种情况下,你有两种可能性
使用goto,并且很高兴,因为它不强制嵌套
这使得代码更具可读性,因为代码只是执行算法所要做的事情。
复制代码,并将其重写为嵌套形式,以便可以 使用结构化的跳转。
这通常会使代码更容易读取,难以维护,而且更大。
帕斯卡语言是后一个问题的主要例子。 因为它没有“break”语句,所以(传统的)Pascal中的循环往往看起来像完全的狗屎,因为你必须添加完全任意的逻辑来说“我现在完成了”。
是否可以接受资源管理? 我应该使用嵌套if语句还是有更好的方法?
更新: 在C中的好Gotos的例子
What is the best way to manage resources for a C program. Should I use a nested if structure or should I use goto statements?
I am aware there is a lot of taboo about goto statements. However, I think it is justified for local resource clean up. I have supplied two samples. One compares a nested if structure and another uses goto statements. I personally find the goto statements make the code easier to read. For those who might argue that the nested if prompt better structure, imagine if the datatype was something other than a char*, like a Windows handle. I feel that the nested if structure would get out of hand with a series of CreateFile functions or any other function that takes large quantities of parameters.
This article demonstrates that local goto statements create RAII for C code. The code is neat an easy to follow. Imagine that as a series of nested if statements.
I understand that goto is taboo in many other languages because their exists other control mechanisms like try/catch etc, however, in C it seems appropriate.
#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; }I would also like to quote Linus Torvalds on goto statements inside the Linux Kernel.
And sometimes structure is bad, and gets into the way, and using a "goto" is just much clearer.
For example, it is quite common to have conditionals THAT DO NOT NEST.
In which case you have two possibilities
use goto, and be happy, since it doesn't enforce nesting
This makes the code more readable, since the code just does what the algorithm says it should do.
duplicate the code, and rewrite it in a nesting form so that you can use the structured jumps.
This often makes the code much LESS readable, harder to maintain, and bigger.
The Pascal language is a prime example of the latter problem. Because it doesn't have a "break" statement, loops in (traditional) Pascal end up often looking like total shit, because you have to add totally arbitrary logic to say "I'm done now".
Is goto acceptable for resource management? Should I use nested if statements or is there a better way?
Update: Examples of Good Gotos In C
最满意答案
使用goto进行清理的好处是不易出错。 不得不释放每个和每个返回点上分配的每个资源,这可能会导致某人某天在执行维护工作时缺少一些清理工作。
也就是说,我会引用Knuth的“结构化编程与转换语句”:
我主张在某些情况下取消转入,并在其他情况下引入。
和Knuth在同一篇论文中对Dijkstra的引用:
“请不要陷入相信我对于[去声明]我非常干涉的陷阱中,我有这样的不舒服的感觉,即其他人正在从中获得宗教信仰,好像编程的概念问题可以通过解决一个简单的编码技巧!“ [29]。
Cleanup using goto has the advantage that it's less error-prone. Having to free each and every resource allocated on each and every return point can lead to someone someday missing some cleanup when doing maintenance work.
That said, I'll quote Knuth's "Structured Programming with goto Statements":
I argue for the elimination of go to's in certain cases, and for their introduction in others.
and Knuth's quote of Dijkstra in that same paper:
"Please don't fall into the trap of believing that I am terribly dogmatical about [the go to statement]. I have the uncomfortable feeling that others are making a religion out of it, as if the conceptual problems of programming could be solved by a single trick, by a simple form of coding discipline!" [29].
发布评论