Skip code without using state variable, using goto envisaged - c++

I have a code which has parts that mustn't be executed if there was an error before in the code. I actually use a bool variable called EndProg that, if set to true, will instruct the program to avoid executing some parts of code.
My problem is that I don't want to use this method and I'd prefer to use goto instead because it will make the program jump to the cleanup part and avoid checking EndProg value multiple times.
The other problem is that I've read on many pages on StackOverflow and other websites that using goto is considered a bad practice and that it can make a code more difficult to read or create errors.
My code is simple enough and I will need to use just one label so I doubt that this will create problems; but I would like to know if there are other ways to do what I want without creating functions to do cleanup tasks or using return (because, for example, I will need to write the cleanup code several times) and I also don't want to write the same big cleanup code in multiple places and then use return or do something else.
I don't want to increase the number of lines of code nor use return nor use a lot of if nor check the value of a state variable. What would you recommend ?
Here's a piece of code :
bool EndProg=false;
/*
Lot of code that can set EndProg to true
*/
ClassType ClassName;
if(!EndProg && LoadConf(&ConfFilePath,&ClassName)==0)
{
int fildes=-1;
if(ClassName.abc) // bool
{
if(ClassName.FilePath==0) // char *
{
ClassName.FilePath=new(std::nothrow) char[9]();
if(ClassName.FilePath!=0)strcpy(ClassName.FilePath,"file.ext");
else EndProg=true;
}
if(!EndProg && mkfifo(ClassName.FilePath,S_IRUSR | S_IWUSR)==-1)
{
if(errno==EEXIST)
{
/* EEXIST is returned if the file already exists
We continue, later we will try to open this file */
}
else EndProg=true;
}
if(!EndProg && (fildes=open(ClassName.FilePath,O_RDWR))==-1)EndProg=true;
}
/*
Lot of code that will check if EndProg == true
*/
}
delete[] ClassName.FilePath;
delete[] ConfFilePath;
What I would like to do is :
bool EndProg=false;
/*
Lot of code that can set EndProg to true
*/
ClassType ClassName;
if(LoadConf(&ConfFilePath,&ClassName)==0)
{
int fildes=-1;
if(ClassName.abc) // bool
{
if(ClassName.FilePath==0) // char *
{
ClassName.FilePath=new(std::nothrow) char[9]();
if(ClassName.FilePath==0)goto cleanup;
strcpy(ClassName.FilePath,"file.ext");
}
if(mkfifo(ClassName.FilePath,S_IRUSR | S_IWUSR)==-1)
{
if(errno==EEXIST)
{
/* EEXIST is returned if the file already exists
We continue, later we will try to open this file */
}
else goto cleanup;
}
if((fildes=open(ClassName.FilePath,O_RDWR))==-1)goto cleanup;
}
/*
Lot of code that will check if EndProg == true
*/
}
cleanup:
delete[] ClassName.FilePath;
delete[] ConfFilePath;
As you can see it isn't difficult to understand and even if searching the label can be a problem for someone, it isn't for me; and I don't plan to make the code public.
Update :
I decided to using exceptions and it works for some parts of my original code. But I doubt this will be easy to implement in more complex parts. Thanks for your answers.

Since you've tagged this question c++ as well I'd go with using exceptions and a try catch block.
You can find a lot of useful information about the subject on SO and on other websites:
Here is a very basic tutorial.
And here is a nice and basic FAQ that might help you as well.
Basically there's nothing to fear, exceptions are not cryptic and in fact make more sense when you get the hang of it. Because basically this concept enables you to achieve exactly what you want:
Several pitfalls that can be handled by the same error handling code.
Edit:
For example if I'd move the mkfifo etc. into a function (in general creating a function for each well defined logical block is clearer and more readable) and have something like
This is just a sketch to give you a general idea:
#include <exception>
functionThatDoesMakeFifo(...){
// check which ever conditions you want to check after mkfifo
// if one of them goes wrong just do:
throw std::exception();
}
// this is inside your function:
ClassType ClassName;
try{
ClassName.FilePath = new char[9](); // even though I'd use a string...
.
.
. // rest of the code
} catch(std::exception &e){
delete [] ClassName.FilePath;
delete [] ConfFilePath;
ClassName.FilePath = NULL; // not mandatory just my habit
ConfFilePath = NULL;
}

I would try with something like Scope Guards or BOOST_SCOPE_EXIT (C++) or its C++11 analogue:
template<class F>
struct ScopeExit
{
ScopeExit(F f) : f(f) {}
~ScopeExit() { f(); }
F f;
};
template<class F>
ScopeExit<F> MakeScopeExit(F f) { return ScopeExit<F>(f); }
#define STRING_JOIN2(arg1, arg2) DO_STRING_JOIN2(arg1, arg2)
#define DO_STRING_JOIN2(arg1, arg2) arg1 ## arg2
#define SCOPE_EXIT(code) \
auto STRING_JOIN2(scope_exit_, __LINE__) = MakeScopeExit([=](){code;})
bool myfunct()
{
ClassType ClassName;
ClassName.FilePath = 0;
ConfFilePath = 0;
SCOPE_EXIT(delete [] ClassName.FilePath; delete [] ConfFilePath; );
if (LoadConf(&ConfFilePath,&ClassName) == 0)
{
int fildes=-1;
if(ClassName.abc) // bool
{
if(ClassName.FilePath==0) // char *
{
ClassName.FilePath=new(std::nothrow) char[9]();
if(ClassName.FilePath==0) return false;
strcpy(ClassName.FilePath,"file.ext");
}
if(mkfifo(ClassName.FilePath,S_IRUSR | S_IWUSR)==-1)
{
if (errno==EEXIST)
{
/* EEXIST is returned if the file already exists
We continue, later we will try to open this file */
}
else return false;
}
if((fildes=open(ClassName.FilePath,O_RDWR))==-1) return false;
}
/*
Lot of code that will check if EndProg == true
*/
}
return true;
}
I'm using return but the cleanup code is just in one place.
Anyway ClassName should take care of cleaning up its own resources in the destructor.

There is a little trick I have seen before that might help you solve this, although I am personally not a fan of tricks, it might be appropriate for what you require.
while (true)
{
if(ClassName.FilePath==0) // char *
{
ClassName.FilePath=new(std::nothrow) char[9]();
if(ClassName.FilePath==0) break;
strcpy(ClassName.FilePath,"file.ext");
}
if(mkfifo(ClassName.FilePath,S_IRUSR | S_IWUSR)==-1)
{
if(errno==EEXIST)
{
/* EEXIST is returned if the file already exists
We continue, later we will try to open this file */
}
else break;
}
if((fildes=open(ClassName.FilePath,O_RDWR))==-1) break;
/*
Lot of code that will check if EndProg == true
*/
break;
}
delete[] ClassName.FilePath;
delete[] ConfFilePath;
But again I am not condoning this as a graceful solution, I personally would re-write your code and break it down into something more readable.
But then again I don't write functions containing hundreds of lines either.

I may get downvoted for this, but I think that limited use of goto in C is not evil. Particularly, what you are talking about is quite acceptable: branching forward to clean up code on errors. I'd suggest that you limit this to a single target label per routine.
What people hate (justifiably) is the old fastion spaghetti code with goto's jumping all over the place.

Related

Is it possible to switch/control/predicate a member function call using a ternary?

The style of this is certainly questionable, but I'm curious if there is a "clean" way in C++ to do a refactor like the following.
Suppose we start with the working code:
if (shapeA.intersects(shapeB)) {
// ... lots of code
} else {
// lots more
}
And I want to do a quick and dirty comparison with my new intersection routine, I'd like to inject a ternary into this if conditional:
if (shapeA.(enable_opt ? intersects_optimized : intersects)(shapeB)) { // expected unqualified-id
// hooray, we are undisturbed
} else {
// lots more
}
As opposed to the pretty awful looking
if (enable_opt) {
if (shapeA.intersects_optimized(shapeB)) {
// ... lots of code
} else {
// lots more
}
} else {
if (shapeA.intersects(shapeB)) {
// trail of tears
} else {
// despair and suffering
}
}
The pain/ugliness involved scales somewhat with the complexity of the conditional inside...
I've tried a few ideas and although it seems like member function pointers are possible to use, it appears impossible to specify a particular overload when obtaining the function pointer for a member variable if that function name is overloaded.
There's a possible 'halfway-house' solution using the ternary which, although still repeating some code, involves only one if ... else test:
if (enable_opt ? shapeA.intersects_optimized(shapeB) : shapeA.intersects(shapeB)) {
// hooray, we are undisturbed
} else {
// lots more
}
Not sure if you count this as 'ugly' or not, though.
You could possibly do it by selecting between pointers-to-member-function, but it wouldn't be very pretty.
Just wrap the call:
bool TestShapeIntersection(const Shape& a, const Shape& b)
{
if (enable_opt)
return a.intersects_optimized(b);
else
return a.intersects(b);
}
Then:
if (TestShapeIntersection(shapeA, shapeB)) {
// hooray, we are undisturbed
} else {
// lots more
}
You can write the ternary as
if ((shapeA.*(enable_opt ? &Shape::intersects_optimized : &Shape::intersects))(shapeB)) {
// hooray, we are undisturbed
} else {
// lots more
}
But it is not a lot prettier.
Note that
you cannot drop the &Shape:: part;
you need the additional pair of parentheses;
it is not exactly idiomatic.
The alternatives that move the call into a helper function are preferable.

Alternitives to C like labling and escaping nested loops for C++

In C and in javascript I enjoy the ability to write this kind of thing and have it just work.
while (a)
{
ctx: while(b)
{
while (c)
{
if(d) break ctx;
...
}
}
...
}
Perhaps I'm just confused about C++ versions but I get this kind of error in g++:
error: expected ‘;’ before ‘ctx’
break ctx;
error: ‘ctx’ was not declared in this scope
warning: label ‘ctx’ defined but not used [-Wunused-label]
ctx:
C++ appears to refuse letting me write this code.
C++ has added lambdas/closures that potentially would let me do this but I'm not quite sure how they would work in this case.
Using try throw catch is the closest construct I can think of that produces this behavior but the sloppiness of using an error system when none should be needed concerns me (Also they are slow I hear).
I'm tempted to just wrap it in extern C except I'm relying on c++ library's completely for the entire project so this also feels sloppy.
Is a try block or just rewriting my only options?
Neither C nor C++ have a labelled break statement (You're probably using a language extension, rather than standard C).
Instead, you can use goto to break out of a nested loop.
while (a)
{
while(b)
{
while (c)
{
if(d)
goto break_b;
}
}
break_b:
// ...
}
I was able to use goto to solve this... I though it was a banned construct in c++?
No. goto is not "banned" in C++.
This is a completely fine way to use goto. There doesn't exist an equivalent structured control statement.
lambdas/closures [...] potentially would let me do this but I'm not quite sure how they would work in this case.
If you are allergic to goto, then you can indeed use a lambda, but I don't see it providing any additional readability:
while (a)
{
[&](){
while(b)
{
while (c)
{
if(d)
return;
}
}
}();
// ...
}
Instead of a lambda, you can use a named function. But in that case you need to pass any variables (such as b, c and d) as arguments (assuming they're not globals).
Yet another way is an extra variable:
while (a)
{
bool break_b = false;
while(b)
{
while (c)
{
if(d) {
break_b = true;
break;
}
}
if (break_b)
break;
}
// ...
}
Of these three methods, I recommend goto, since it's the most readable. Except in the case the actual inner loop omitted from the example is very long, in which case a separate function might be better.
As has already been pointed out by others, goto would be a way to do exactly what you're asking for.
That being said, I would argue that, before asking the question of how to break out of a massively-complicated control flow structure, you should first ask yourself why there is a massively-complicated flow structure to begin with. What is going on in these loops? Should whatever is going on in each of these loops not better be moved into its own function? For example, instead of
while (a)
{
ctx: while (b)
{
while (c)
{
if (d) goto ctx;
…
}
}
…
}
why not
bool doC()
{
while (c)
{
if (d)
return false;
…
}
return true;
}
void doB()
{
while (b && doC());
}
and then
while (a)
{
doB();
…
}
Replacing the break with a goto here is not advisable. There can be issues wrt constructors and destructors not being called correctly. Whilst goto still exists in C++, it's really not something you want to use unless you really know what you're doing! A safer option would be to use a try-catch block. A better approach would be to re-factor your algorithm (currently it's O(N^3), which should really be ringing some alarm bells!)
while (a)
{
try
{
while(b)
{
while (c)
{
if(d) throw;
}
}
}
catch(...)
{
}
}

C - do{..} while(0); can be removed from code excluding usage nested if else?

do{...} while(0);
the usage of do{}while(0); in my coding is used because, i do not want to use long if else nested conditional statements. I eventually give an break at the time of failure and move out of the loop, with a assurance that my function would have been traversed at least 1 time.
Now, the problem comes with the code warning tools, I am getting a warning at the usage of do{...}while(0);
the usage of nested if(){} else{} is less readable, high complex. and lets the code to be having dead code.
if i exclude nested if(){} else{} and do{} while(0); , do we left part with some other way to make code readable with understandable logic;
if(status_of_funcA_ok != funcA())
{ //failure}
else if (status_of_funcB_ok != funcB())
{//failure}
else if (status_of_funcC_ok != funcC())
else
{//Great}
do{
if(status_of_funcA_ok != funcA())
break;
if (status_of_funcB_ok != funcB())
break;
if (status_of_funcC_ok != funcC())
break;
}while(0);
Move the complete logic of the do while{0} loop to a function, and replace the break with return. And call the function, instead of the loop.
You will not have to worry about the beauty.
The compiler also doesn't have to complain about the do while{0}.
All the more, by adding a bit of modularity, the program might be a little more readable.
In any case, before doing this, it would be nice to check whether your compiler is in an extremely pedantic mode, and you might want to turn that off. That might take the warning away.
ss.
PS: You don't seem to need a return value for the function, but you could have that to get a clue of which function was successful.
I am using this pattern too, for those who wonder, here's an abstract example:
do // while(0) for break
{
state1 = 0;
if (cond1())
{
if (cond2())
break;
state1 = opA();
}
if (cond3() || state1 && state1->cond4())
break;
...
Triumph(state1, ...);
// often here: return
}
Failure(state1, ...);
I consider this valid in the following circumstances:
you have a long-ish sequence (say, >~half a dozen of conditions)
the conditions are complex, and you use / build up significant state, so you can't
isolate the elements into functions
you are in an exception-unfriendly environment, or your break-ing code path is
not actually an exception
What you can do about it:
Silence the warning. It is just a warning, after all; and I don't see a "typical mistake" (like typing 0 instead of your condition) that would be caught by this warning.
[edit] Now, that was silly. the typical mistake that you catch with the warning is e.g. while (a1!=a1) instead of while (a1!=a2).[/edit]
Break into functions, move state to a class
this would transform above code to:
struct Garbler
{
State1 state1;
bool Step1()
{
state1 = 0;
if (cond1())
{
if (cond2())
return false;
state1 = opA();
}
return true;
}
bool Step2()
{
return cond3() || state1 && state1->cond4();
}
..
void Run()
{
if (Step1() && Step2() && ... && Step23())
Triumph(state1, ...);
else
Failure(state1, ...);
}
}
This is arguably less readable, worse is that you pull apart the sequence, which might lead to a very questionable class (where members may be called only in a certain order).
Scopeguards
This may allow to transform the breaks into early returns, which are more acceptable:
state1 = 0;
ScopeGuard gFailure = MakeGuard(&Failure, ByRef(state1), ...);
if (cond1())
{
if (cond2())
return;
state1 = opA();
}
if (cond3() || state1 && state1->cond4())
return;
// everything went ok, we can dismiss the scopeguard
gFailure.Dismiss();
Triumph(state1, ...);
They can be more elegantly written in C++0x, preserve the flow, but the solution isn't that flexible either, e.g. when Failure() cannot be isolated easily into a single function.
Nested nested if-else statements can become quite unreadable, but I think using do {..} while(0); as a replacement would be much worse. It is very unconventional and anybody else reading it would not really associate it with if-else statements.
There are a few things you can do to make nested if-else statements more readable. A few suggestions are:
optimize your logic - sometimes you can do away with a lot of if clauses when you 'refactor' your logic ex. grouping identical items.
use switch() - switch is generally more readable compared to if-else statements. You can associate an enum to each case and you can switch this.
encapsulate complicated logic with functions
You can use goto instead of do {} while(0) and break. This is not readable and not good practice either though. I think for each specific case there is a better way to avoid deep if/else structures. For example, sometimes using function calls can help:
for example instead of:
if(status_of_funcA_ok != funcA())
{ //failure}
else if (status_of_funcB_ok != funcB())
{//failure}
else if (status_of_funcC_ok != funcC())
else
{//Great}
you can write:
if (check_funcs() == 0) {
great();
}
int check_funcs() {
if (status_of_funcA_ok != funcA())
return -1;
if (if(status_of_funcB_ok != funcB()))
return -2;
if (if(status_of_funcC_ok != funcC()))
return -3;
return 0; /* great */
}
Sometimes, you can use exit().
Also, in c++ you can use throw() and try/catch:
try {
/* */
throw (this error);
/* */
throw (that error);
} catch (this error) {
} catch (that error) {
}
If there are more conditions to check avoid using if{} else{},
best practice is to Replace if else conditions with switch case

C or C++ Return Status

What are the best practices for writing C or C++ functions that return an int that represents a status code?
Specifically, I want to know about the client usage but other tips are welcome.
For example, can I write something like this:
int foo() {
return 0; // because everything was cool
}
And then use it like this?
if (foo()) {
// what to do if false, e.g. non-zero, e.g. not OK
} else {
// what to do if true, e.g. zero, e.g. OK
}
This should work because best practices typically dictate that a status code of 0 means everything was OK and also 0 means false in a boolean statement.
However, this wouldn't be good, right:
if (!foo()) {
// what to do if true
} else {
// what to do if false
}
We use this in C where I work:
int err = foo();
if (err) {
// armageddon
}
The assignment and if could be combined, but with more complicated function calls it gets more confusing and some people are confused by assignment in a conditional (and gcc hates it).
For C++, I would prefer exceptions if available, otherwise the above.
Edit:
I would recommend returning 0 on success and anything else on error. This is what unix command line utilities do.
If you really want to use status codes that way, use them with an enum or block of #define statements that describe the intention of the status code.
For example:
enum
{
kSuccess = 0,
kFailure = -1,
}
function foo()
{
return kSuccess;
}
if (kSuccess == foo())
{
// Handle successful call to foo
}
else
{
// Handle failed call to foo
}
This way, the intention is clear and there's no error-prone guesswork when someone wants to use or maintain your code in the future.
if (foo()) {
// what to do if false
} else {
// what to do if true
}
The problem with this approach is excess nesting. Suppose you have three functions you want to call:
if(foo1()) {
if(foo2()) {
if(foo3()) {
// the rest of your code
} else {
// handle error
}
} else {
// handle error
}
} else {
// handle error
}
To solve the excess nesting problem, invert the return value:
if(!foo1()) {
// handle error
return;
}
if(!foo2()) {
// handle error
return;
}
if(!foo3()) {
// handle error
return;
}
This solution suffers from another problem. It mixes the program logic with the error handling code. This complicates everything. Ideally, you want the program logic and error handling separated. This problem can be fixed with the goto
if(!foo1())
goto error1;
if(!foo2())
goto error2;
if(!foo3())
goto error3;
return;
error1:
// handle error
return;
error2:
// handle error
return;
error3:
// handle error
return;
Much cleaner.
Also, the goto can solve the problem of resource deallocation. See Using goto for error handling in C by Eli Bendersky for more details.
The return statuses should be defined in your interface and known to the caller. Some return 0 on failure (because it's easy to check with !), some return 0 on success (because they have enum of error codes, with OK being the first item).
There's no law or standard, each interface defines its own conventions. In C++ - use exceptions.
Best practice is to document your code so that yourself and others can quickly look up what the return codes will be when doing error checking.
Just jumping on board with another option that may be appropriate in your circumstances:
enum fooret { GOOD, BAD, UGLY, WORSE };
fooret foo(); // defined elsewhere
switch(foo())
{
case BAD:
case UGLY:
// maybe a recoverable failure(s)...
// take appropriate actions
break;
case WORSE:
// maybe non-recoverable
break;
case GOOD:
// successful, take appropriate actions
break;
}
int foo() {
try{
...
return 1
}
catch
{
return 0; // because everything was cool
}
}
I would start by wrapping everything in a try/catch block. Also instead of using and int it might make more scene to return a Boolean value. This is just a little more intuitive when testing in the if statement.

Style question about existing piece of code (C/C++)

I just hope the following doesn't seem to you like redundant jabber :)
Anyway, there is that:
for (p = fmt; *p; p++) {
if (*p != '%') {
putchar(*p);
continue;
}
switch (*++p) {
/* Some cases here */
...
}
}
And I wondered why the writer (Kernighan / Ritchie) used the continue in the if statement.
I thought it was for the mere reason that he deemed it would be more elegant than indenting the whole switch under an else statement, what do you think?
Probably. The human brain has limited stack space, making it difficult to deal with deeply nested structures. Anything that flattens the information we're expected to parse makes it easier to understand.
Similarly, I normally prefer this:
bool foo(int arg)
{
if(!arg) {
/* arg can't be 0 */
return false;
}
/* Do some work */
return true;
}
To this:
bool foo(int arg)
{
if(!arg) {
/* arg can't be 0 */
return false;
} else {
/* Do some work */
return true;
}
}
Or worse, to this:
bool foo(int arg)
{
if(arg) {
/* Do some work */
return true;
} else {
/* arg can't be 0 */
return false;
}
}
In the last example, the part that does the work might be quite long. By the time the reader gets to the else clause, he may not remember how he got there.
Putting the bail out conditions as close to the beginning helps to assure that people who try to call your functions will have a good idea of what inputs the function expects.
Also, as others pointed out, the continue makes it clear that there's no need to read further into the code inside the loop to determine whether any more processing is done after that point for this case, making the code easier to follow. Again, the fewer things you force the reader to keep track of, the better.
Because with the continue it is clear that the code is done for this loop iteration. If a else would have been used you had also to check if there is no code after the else.
I think it is general a good habit to exit a context as soon as possible because this leads to much clearer code.
For example:
if(arg1 == NULL)
return;
if(arg2 == NULL)
return;
//Do some stuff
vs.
if(arg1 != null)
{
if(arg2 != null)
{
//Do some stuff
}
}
It is just so much easier to read when it's put like this.
Are we done here with this iteration through the loop? Yes? So let us continue with the next iteration.
I think that he would have reasons enough to indent the code under the switch, and indenting the entire meat of the function is quite wasteful of horizontal space. At the time the code was written, I imagine 80 character widths were still popular.
I don't think it is difficult to understand, but I do think that it's quite nice to mention what you DON'T do immediately, and then GTFO.
There are always many ways to write code like this -
Putting the entire switch inside an else statement would be perfectly valid. I suppose the reason they did it this way ~may~ have been just the way they were thinking at the time:
"if the value at p does not equal '%', put then continue on."
If you have switch under an else, it may not have been as obvious to the writer that you were jumping to the next iteration in that specific case.
This is completely personal style choices, though. I wouldn't worry too much - just write it in a way that makes the most sense to you and your team.
I agree.
But you can't look at it as a "mere reason", it's actually a pretty good reason, because it reduces the over all complexity of the code. Making it shorter and easier to read and understand.
If you use an else then everything inside the else needs to be indented:
if ()
{
doA();
}
else
{
doB();
if ()
{
doC();
}
else
{
doD()
}
}
If you use continue then you don't need to indent:
if ()
{
doA()
continue;
}
doB();
if ()
{
doC();
continue;
}
doD();
Also, continue means that I can stop thinking about that case: for example, if I see else then perhaps there'll be more processing of the '%' case later in the loop, i.e. at the end of the else statement; whereas on seeing continue I know instantly that the processing of the '%' case in the loop is completely finished.
The most probable reason is that the switch that follows is rather long - this looks like printf format parsing.
There could be more that one reason to continue/break a loop. So it would look next:
loop
{
if (cond1)
{
if (cond2)
{
if (cond2)
{
more conditions...
}
}
}
else
{
the loop action
}
}
IMHO it's not so elegant and readable as the loop in your example, e.g:
loop
{
if (cond1)
continue;
if (cond2)
continue;
if (cond2)
continue;
if( more conditions...)
continue;
the loop action
}
And you don't even need to understand all structure of all "if"s (it could be much more complex) to understand the loop logic.
P.S. just for the case: I don't think the authors thought about how to write this loop, they just wrote it:)
I stick to Dijkstra's teachings: goto is harmful. And continue/break are goto's little brothers.
If the problem is that you're indenting the code too much, the solution is not putting a continue in the loop, but reducing the complexity by separating the code in different functions or thinking about a better way of organizing it.
For example, #Kamarey snippet would be even clearer like this:
loop
{
if (!(cond1 ||
cond2 ||
cond2 ||
...))
{
the loop actions;
}
}
or #Ori Pessach example could be expressed like:
bool foo(int arg)
{
if(arg) {
/*do some work*/
}
return arg != 0;
}
In brief, usually I can't find a good enough reason to use non structured programming constructs (maybe for some cleanup codes in a very limited ocasions...)
Well, I wrote C programs for about 11 years and I had to read 5 times your piece of code to understand it !
Kernighan and Ritchie were active in the sixties. At that time, being able to understand a piece of code was not relevant. Being able to write code that fit in 16 Ko was.
So I'm not suprised. C is a terrible language when your teatchers are K & R. Just look at realloc : who would know code something like that today ? In the '60ies, it was all the rage, but it is now appalling, at least :o)