- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
People have been asking why do{...}while(0) is useful in C. One reason is to force macros to have the same syntax as functions. Consider the line:
for(i=0;i<5;i++) MYMACRO(i);
If MYMACRO is a naive multi-line macro, then we've got trouble: only the first line will be associated with the for! (Also, the semicolon is superfluous, though that's not fatal.)
So instead, you define MYMACRO to be do{...}while(0), which transforms multiple lines into one line, and then the above construction works fine. (Also, the semicolon is no longer superfluous)
Admin
If you want to use a goto, use a goto. Replacing it with misused structure is not at all better.
Admin
or just switching the order of the conditionals in the second part of the for loop.
I am pretty certain this is C++ because of the UINT32, the GetSize() and the use of the comparison operator !=.
It is incorrect usage of C++ but complies with the language.
[i]Addendum (2010-08-26 06:26): The correct way to do it is the way I outlined on Page 1 it must have been too clsoe to the bottom of the page so I will try to post the correct implementation again. You can do all of this in one statement.
Admin
Step 1: Get rid of all the nonsense Hungarian notation and use standard STL collections.
Step 2: Refactor that into one statement:
If you can't refactor into STL collections there are still ways to create proper iterators for it so you can use std::equal. &modelPartsToLoad[0] might work if the collection is guaranteed to be contiguous.
Admin
Why make it so complicated. If you want to force it to run at least one iteration, use do/while, if you want to check the condition before doing any iterations, use while or a for loop.
Admin
Those are the only bugs I could find :(
had forgotten my BASIC error numbers, googled for a reference and good lord! Someone is working on a 64 bit edition of qbasic that supports Linux and Windows. I felt dirty after discovering this.
How well do you know javascript / DOM trees, are you familiar with greasemonkey, and how much beer do I owe you?Admin
What it's really called is "Aspect-Oriented Programming".
But in that case the developer of the platform code KNOWS that he will jump into other people's code.Admin
This is a variation of a pattern that allows error handling in a single place if you're using a language like C that doesn't support exceptions. It's probably better to use a goto:
However, there are a lot places where using a goto even where it makes sense is irrationally considered very bad practice. In a situation like that, it might make sense to use the break statement as in the example.
A better way to handle that situation (if the "goto error;" isn't permitted or desired) might be to use a "do {} while (false)" statement instead of a "for (;;) {}".
Admin
DE-WTF:
Admin
You don't have to complete the inner loop as it's just looking for the first occurrence of inequality.
Admin
It amazes me how stupidly people will code, just to avoid a GOTO.
http://slashdot.org/journal/145833/In-defense-of-GOTO
The "Do ONCE" construct is a common anti-pattern.
Admin
The scenario referred to in the article is only applicable for the C language.
In C++ you have RAII, which effectively involves creating scoped objects whose destructors invoke when they go out of scope. As a result you do all your "clean-up" in those.
There there is no need for goto or finally in try-catch blocks.
Admin
Let us see, gotos are uncivilized and the workarounds just plain ugly. I know! I use goto but wrap it up to some macros to make it more structured. At least it directly spells no goto in the source file, so aren't you happy?
Used in a simple parser program.
Admin
Actually, I have also seen this kind of code, except that the programmer mask it in macros like
BEGIN_BS BREAK_IF( cond ); BREAK_IF_WITH( cond, var = value ); END_BS
I first read the BS as you know, BS. And I think it is utter BS.
Admin
Sure, this particular case might have been structured better, but in general this isn't a bad pattern. In VB, I've seen Do ... Loop While False used a lot, especially where some things need to be done, then a check, then some more actions, another test, and so on. Such code is much clearer than the equivalent with Gotos, and a lot less Alpine than nested Ifs. The language just doesn't have Do ... Once and you can't blame the coder for that. In C++ you might do something like ‘#define once while(false)’ although then ‘once { ... }’ won't do what you expect at all... You might ‘guard’ yourself against this with an extra semicolon, but that actually causes a more insidious problem. All in all, I prefer not to use #defines this way.
You know you're hard core when you're missing your favourite Intercal command.Admin
Uh?
This is quite common, actually.
And quite useful, too.
GOTO will not eat your soul, despite what the Church of the Holy Syntax might say, and tricks such as this one are even more harmless.
Did you really say you would have preferred three nested ifs? WTF?
Admin
It's possible that this is just for historical reasons. It may have originally done something in the for() loop which was removed, leaving the code looking like that.
Admin
(replying to myself) ‘#define once while(false);0’ works, since the 0 can't be followed by an { or most statements, so the temptation of writing ‘once { ... }’ won't be there. But is harmless when followed by a ; except when the next statement is an else: ‘if(...) do { ... } once; else ...;’ is invalid. It could be rewritten as ‘do { if(!...) { ...; break; } ... } once;’ but I still think that the preprocessor solution isn't ideal and I won't use it.
Admin
Yet you fail to elaborate the reasons why the rule was invented. Goto isn't evil because it is spelled g-o-t-o.
One reason not to use goto is that program flow can jump to anywhere. You have to find the label to know where execution is going to jump to.
Not with 'do {} while (0);' - this jumps to the end of the block which is easily located.
When you encounter a label in the source, the gotos leading there may again be anywhere in the code. No problem with 'do {} while (0);' because all the breaks have to be in the braces.
Jumping into a construct is an issue with a real goto but it isn't possible with 'do {} while (0);'.
Calling 'do {} while (0);' a goto is misleading, nay, outright wrong, except if you call it a structured goto ;-)
Personally I prefer 'switch (0) { default:' on one line, and a comment above it. The 'while ()' and 'for (;;)' constructs make people expect a loop that isn't there - and there is even the theoretical risk of an infinite loop if you manage to misplace a 'continue'.
There are lots of things that "everybody knows" that have no foundation.
Admin
I don't, and I make my own opinion instead of taking a tool's output for canon.
A return ensures that execution flow cannot reach those points that it should not reach, so there's no need for elaborate if () conditions or else chains.
Admin
Good article you post! It enlarge my knowlege on the point!Thank You for the post. I love to read interesting post that has knowledge to impart. I hope to read more articles from you and in return I will post also my articles in the forum so that others can benefit from it. Keep up the good work!
Admin
Or, in a slightly pascalish manner, one could define a single variable where to put the return value and use goto to get to the return statement at the end of the function.
Though that would equally sic the purists after my ass, which is ironic, as I've heard more than once "a nested function with multiple return points as a structured substitute of goto." Supposedly those people have misunderstood the purest meaning of structured programming.
Admin
well
i am not sure, why they always use a for look for this construct
a better way could have been another loop:
do {
if 1... break; if 2... break; break; <--- can now be ommited } while (FALSE);
Admin
ROTFLOLOLOLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOLLOL
Admin
The main issue here is that it's a borderline case.
Consider what's really happening.
Sure, that could be done as an if/else with little change.
But really. Multiple functions? Multiple returns from a function? For this code? Personally, I go through code where people have lazily peppered returns randomly all over their functions and refactor them to have single flow - for me functions are much easier to follow when they enter and exit in one place, not to mention easier to handle in a debugger, something that far too few developers actually use. With a single point of return, there's none of this "Oh ... I didn't see that return buried in the middle of that if/else in the for loop."
I would not use the construct given for something that simple; in fact I wouldn't use it at all because
is very commonly used to mean "forever".On the other hand, I use do{}while(0); very often for cases such as the following:
All the if/else-happy happy folks would be stuck doing something like the following (which I've seen far too many places in our code):
Note: the real WTF is that the Java folks realized what the C++ folks didn't - a simple named break solves this quite cleanly without introducing the randomness of a GOTO:
Now, that is code that has obvious purpose and design without having to hope that intent is clear because the language is not.
Admin
Ah, c'mon. There are sometimes legit reasons for that sort of construction in C: one-stop resource cleanup. Something like:
It's definitely safer/less cumbersome to have all the cleanup code in one place, rather than writing a 'return' where I have each 'break', and trying to make sure you do the right cleanup in each place.
Sure, you can do the same with a 'goto' but this is, I think, a little cleaner. It should be self-evident that the final clauses get allocated.
Something like try-finally would be better, but if your language don't got that, you have to make one up.
(But note do-while(0) rather than for(ever))
Admin
Let me clarify here a few things about this.
This particular example is ridiculous and if you are defending this style of coding I can only say I'm happily not working with you. A few programmers here I shared this with said wtf and suggested I submit it.
Admin
Yes, that's sublime dude!