Quote:Original post by Zahlman
Stuff
That's indeed very elegant.
Thank you for an excellent answer, as always.
Quote:Original post by Zahlman
Stuff
Quote:Original post by AcidZombie24
I want to make clear that when i used alloca, i meant alloca and NOT malloc. Malloc you free, alloca you dont. Malloc you can allocate tons of memory, alloca you cant (remember, its on the STACK).
Zahlman:
>Wait, what?
The 'other' time i use gotos, are when i need to break out of 2 loops. The break keyword unfortunately only breaks out of the current loop. I would like a break 2; keyword. (i never needed 3 but why not have it)
label: for (stuff) { for (other stuff) { if (weird thing) { break label; } }}
Quote:Original post by implicit
The enmity towards goto has got to be more tradition than anything else at this point. In the dawn of time goto-dominated spaghetti code was a real problem, and the invention and adoption of structured programming languages was a great step forward.
Quote:Now, thirty years later, people still spend large amounts of time discussing whether goto may be the best solution to some specific problem in some specific language, but it doesn't change the fact that either way no one is advocating using them in more than a handful of idiomatic cases poorly handled by the existing control structures so their impact is essentially zero. Not even the basic converts seem to be trying to abuse goto anymore.
Quote:I mean honestly on the list of hard or just plain fucked up things in C/C++ goto is just not on the radar..
Quote:Oh, by the way there is one classic uncontroversial case where goto is useful: code generators.
Quote:Original post by ZahlmanI honestly haven't actually read more than a small bit of Linux kernel code so I couldn't say but frankly I don't think I've seen anything resembling real goto abuse in code less than a decade old (or possibly written by a newbie).
There are some pretty egregious (ab)uses in the Linux kernel code. The *actually* "idiomatic" cases are in fact not so "poorly handled by existing control structures", either. This is an excuse made by inexperienced programmers, who either haven't thought about it very hard, or got scared off by a nasty "general-case solution", or both.
Quote:I'm not convinced. If you're smart enough to write code that doesn't use goto, and you're smart enough to write code that writes code, why wouldn't you be smart enough to write code that writes code that doesn't use goto?Well.. So far my (admittedly feeble) attempts at writing compilers have generally involved translating all control structures into generalized forms of goto, it is after all the textbook way of doing things. Now if you want to spend a bunch of extra code recreating the best-matching C structures to make the code readable or more easily optimized, then that's fine, but in practice you'd rarely bother.
Quote:Original post by implicitQuote:I'm not convinced. If you're smart enough to write code that doesn't use goto, and you're smart enough to write code that writes code, why wouldn't you be smart enough to write code that writes code that doesn't use goto?Well.. So far my (admittedly feeble) attempts at writing compilers have generally involved translating all control structures into generalized forms of goto, it is after all the textbook way of doing things. Now if you want to spend a bunch of extra code recreating the best-matching C structures to make the code readable or more easily optimized, then that's fine, but in practice you'd rarely bother.
Interestingly I once wrote a static recompiler which relied on tail-recursion and short functions rather than a gigantic goto mess to get extra performance. The downside here is that it wouldn't run in debug mode since the stack exploded without tail-recursion optimizations on.
Quote:Original post by ZahlmanIt may be the poor man's portable assembly language but it's nevertheless damned useful and popular for just this purpose ;)
Oh, you meant *that* kind of code generation. I was thinking of very large systems, genetic programming, code-as-data approaches to configuration info etc. True, the machine - and any sane bytecode - is going to implement everything with jumps anyway, and using C as a target is just a shortcut (though it's the poor man's shortcut) to portability.
Quote:Tail recursion should be convertible to plain iteration without goto fairly easily in normal cases, though?Yeah, usually. But in this case I was merely abusing tail recursion to implement goto when translating assembly language code to C, something which can feature some *truly* weird control flows and special cases.
Quote:Original post by LessBread
Correct me if I'm wrong, but I have the impression that goto labels must be unique. That is, "error:" could only be used once rather than reused again and again in various functions. Perhaps this behavior is compiler specific and that explains why this drawback is forgotten during discussions on the propriety of using goto.
void a(){ goto foo; foo:}void b(){ goto foo; foo: // okay!}void c(){ if(qux()){ goto foo; foo: } while(bar()){ goto foo; foo: // errorized! }}
Quote:Original post by Gage64
Like I said, my example was illustrative. You are assuming that you can perform further operations (attempt to open a file) even if previous operations failed (the memory allocation). In your code, that's true, but what if one operation depends on a previous operation being successful? If the previous operation failed, you cant continue - you have to exit the function immediately, while making sure to cleanup any allocated resources.
...int * arr = malloc(...);if(arr) { FILE * file = fopen(...); if(file) { /* normal operation */ ... fclose(file); } else { /* file open error reporting */ } ... free(arr);} else { /* memory allocation error reporting */}
Quote:Still, it does show that elegantly avoiding a goto is not as hard as I thought in this particular case.