repeated code before multiple return statements

A

Alexander Stoyakin

Hello!
Please advise on the following issue. I have a function which returns
1 or 0 in multiple branches, and it must perform the same code before
each return, like this:
int fun()
{
if (some code)
{
restore(param1,param2,param3,param4,param5);
return 1;
}
else if (some code)
{
restore(param1,param2,param3,param4,param5);
return 0;
}
restore(param1,param2,param3,param4,param5);
return 1;
}

Is there any alternative way to execute some code upon return from the
function in pure C? Repeated code makes my function more than twice
longer and it losts its readability. The only thing coming to my mind
is goto.

Thanks, Alex.
 
K

Kenneth Brody

Alexander said:
Hello!
Please advise on the following issue. I have a function which returns
1 or 0 in multiple branches, and it must perform the same code before
each return, like this:
int fun()
{
if (some code)
{
restore(param1,param2,param3,param4,param5);
return 1;
}
else if (some code)
{
restore(param1,param2,param3,param4,param5);
return 0;
}
restore(param1,param2,param3,param4,param5);
return 1;
}

Is there any alternative way to execute some code upon return from the
function in pure C? Repeated code makes my function more than twice
longer and it losts its readability. The only thing coming to my mind
is goto.

What about something like this?

int fun()
{
int retval;

if ( some code )
retval = 1;
else if ( some other code )
retval = 0;
else
retval = 1;

restore(param1, param2, param3, param4, param5);

return retval;
}

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
B

Ben Pfaff

Alexander Stoyakin said:
Please advise on the following issue. I have a function which returns
1 or 0 in multiple branches, and it must perform the same code before
each return, like this:
int fun()
{
if (some code)
{
restore(param1,param2,param3,param4,param5);
return 1;
}
else if (some code)
{
restore(param1,param2,param3,param4,param5);
return 0;
}
restore(param1,param2,param3,param4,param5);
return 1;
}

int fun2()
{
if (some code)
return 1;
else if (some code)
return 0;
else
return 1;
}

int fun()
{
int retval = fun2();
restore(param1,param2,param3,param4,param5);
return retval;
}
 
C

C. Benson Manica

What about something like this?

int fun()
{
int retval;

if ( some code )
retval = 1;
else if ( some other code )
retval = 0;
else
retval = 1;

restore(param1, param2, param3, param4, param5);

return retval;
}

How about

int retval = ( some_code || !some_other_code ) ? 1 : 0;

restore(param1, param2, param3, param4, param5);
return retval;

?

(Depending on what some_code and some_other_code actually are, this
may not be readable in practice.)
 
R

Roberto Waltman

Alexander said:
..I have a function which returns
1 or 0 in multiple branches, and it must perform the same code before
each return, like this:
int fun()
{
if (some code)
/* let's call this condition_1 */
{
restore(param1,param2,param3,param4,param5);
return 1;
}
else if (some code)
/* let's call this condition_2 */
{
restore(param1,param2,param3,param4,param5);
return 0;
}
restore(param1,param2,param3,param4,param5);
return 1;
}

Is there any alternative way to execute some code upon return from the
function in pure C? Repeated code makes my function more than twice
longer and it losts its readability. The only thing coming to my mind
is goto.

Assuming the parameter lists param1..5 are identical, you wrote this:

int fun()
{
int ret_val = 1;
if (condition_1)
{
}
else if (condition_2)
{
ret_val = 0;
}
restore(param1,param2,param3,param4,param5);
return ret_val
}

Assuming "condition_1" and "condition_2" do not contain function calls
or have side effects, you wrote this:

int fun()
{
int ret_val = 1;
if (condition_2)
{
ret_val = 0;
}
restore(param1,param2,param3,param4,param5);
return ret_val
}


Roberto Waltman

[ Please reply to the group,
return address is invalid ]
 
S

santosh

Alexander said:
Hello!
Please advise on the following issue. I have a function which returns
1 or 0 in multiple branches, and it must perform the same code before
each return, like this:
int fun()
{
if (some code)
{
restore(param1,param2,param3,param4,param5);
return 1;
}
else if (some code)
{
restore(param1,param2,param3,param4,param5);
return 0;
}
restore(param1,param2,param3,param4,param5);
return 1;
}

Is there any alternative way to execute some code upon return from the
function in pure C? Repeated code makes my function more than twice
longer and it losts its readability. The only thing coming to my mind
is goto.

Two possibilities, among others:

int fun()
{
int retcode;

if(exp1) retcode = 1;
else if(exp2) retcode = 0;
else retcode = 1;

restore(p1, p2, p3, p4, p5);
return retcode;
}

or

int fun()
{
restore(p1, p2, p3, p4, p5);
if (exp1) return 1;
else if (exp2) return 0;
else return 1;
}

HTH
 
W

Walter Roberson

Roberto Waltman said:
Assuming the parameter lists param1..5 are identical, you wrote this:
int fun()
{
int ret_val = 1;
if (condition_1)
{
}
else if (condition_2)
{
ret_val = 0;
}
restore(param1,param2,param3,param4,param5);
return ret_val
}
Assuming "condition_1" and "condition_2" do not contain function calls
or have side effects, you wrote this:
int fun()
{
int ret_val = 1;
if (condition_2)
{
ret_val = 0;
}
restore(param1,param2,param3,param4,param5);
return ret_val
}

Let condition_1 be param1 == 0
Let condition_2 be 1/param1 > param2
Then condition_1 and condition_2 do not contain function calls
or have side effects, but your revised code would go directly to

if (1/param1 > param2)
{
ret_val = 0;
}

which is going to fail if param1 is 0 -- the condition protected
against in condition_1 .
 
C

CBFalconer

Alexander said:
Please advise on the following issue. I have a function which returns
1 or 0 in multiple branches, and it must perform the same code before
each return, like this:
int fun()
{
if (some code)
{
restore(param1,param2,param3,param4,param5);
return 1;
}
else if (some code)
{
restore(param1,param2,param3,param4,param5);
return 0;
}
restore(param1,param2,param3,param4,param5);
return 1;
}

Is there any alternative way to execute some code upon return from the
function in pure C? Repeated code makes my function more than twice
longer and it losts its readability. The only thing coming to my mind
is goto.

int fun() {
int flag;

flag = 1;
if (some code) flag = 1;
else if (some other code) flag = 0;
restore(.....);
return flag;
}
 
C

Christopher Benson-Manica

santosh said:
int retcode;

if(exp1) retcode = 1;
else if(exp2) retcode = 0;
else retcode = 1;
restore(p1, p2, p3, p4, p5);

Given this...
restore(p1, p2, p3, p4, p5);
if (exp1) return 1;
else if (exp2) return 0;
else return 1;

....it seems unlikely (but possible) that OP will want to restore()
anything prior to the evaluation of exp1 and exp2.
 
A

Al Balmer

How about

int retval = ( some_code || !some_other_code ) ? 1 : 0;

restore(param1, param2, param3, param4, param5);
return retval;
That will work for "this", but no necessarily "something like this"
:) I think the OPs example was intended to be illustrative, not
necessarily his exact need.

Kenneth's solution is good, and easily generalized. Both solutions
have the desirable feature of making it plain that the "some (other)
code" affects only the return value, not the processing, and
eliminating multiple returns. (I'm not always opposed to multiple
returns, but there's no excuse for them here.)
 
C

Christopher Benson-Manica

Al Balmer said:
On Fri, 27 Jul 2007 18:10:07 -0000, "C. Benson Manica"
That will work for "this", but no necessarily "something like this"
:) I think the OPs example was intended to be illustrative, not
necessarily his exact need.

I think I covered the possibility that it might not be what OP was
looking for, and for sure if the real code has many branches the
conditional operator should be banished from consideration. (This is
all MHO, incidentally, as I have already been reminded today that I am
not the Pope...)
 
G

Gene

Hello!
Please advise on the following issue. I have a function which returns
1 or 0 in multiple branches, and it must perform the same code before
each return, like this:
int fun()
{
if (some code)
{
restore(param1,param2,param3,param4,param5);
return 1;
}
else if (some code)
{
restore(param1,param2,param3,param4,param5);
return 0;
}
restore(param1,param2,param3,param4,param5);
return 1;

}

Is there any alternative way to execute some code upon return from the
function in pure C? Repeated code makes my function more than twice
longer and it losts its readability. The only thing coming to my mind
is goto.

Thanks, Alex.

Good question. This is one situation that inspired the development (a
long time ago) of exception mechanisms. To generalize your example a
little, many functions that honor unix return code standards are
structured like this...

int fun(...)
{
...
if (<condition1>) {
<cleanup code>
return 1;
}
< normal processing 1 >

...
if (<condition2>) {
<cleanup code>
return 2;
}
...
< normal processing 2>
... yada yada ...

return 0;
}

This is really annoying when (as usual) the cleanup code needs access
to many local variables. In a block structured languate with nested
functions, you would define a cleanup function with access to those
variables. In pseudo-C,

int fun(...)
{
<local var decls>

int cleanup(int return_code)
{
<cleanup code>
return return_code;
}

...
if (<condition1>) return cleanup(1);

< normal processing 1 >

...

if (<condition2>) return cleanup(2);

...
< normal processing 2>
... yada yada ...

return 0;
}

Since C doesn't have nested functions, one way to go is "fake" them
with macros. This strategy is far from ideal, but it does have a
rationale. It avoids the problems of goto's and introducing a very
long-lived "ret_val" variable, which has maintenance problems.

int fun(...)
{
<local var decls>

#define CLEANUP_AND_RETURN(N) do { \
<cleanup code> \
return (N); \
} while (0);

...
if (<condition1>) CLEANUP_AND_RETURN(1);

< normal processing 1 >

...

if (<condition2>) CLEANUP_AND_RETURN(2);

...
< normal processing 2>
... yada yada ...

return 0;

#undef CLEANUP_AND_RETURN
}

Another way to go is bottle up all the local variables needed for
cleanup in a struct so that a non-nested cleanup function can do its
work.

struct foo_vars_s { <local var decls };

int cleanup(int ret_val, struct foo_vars_s *o)
{
<cleanup code accessing variable x as o->x >
return ret_val;
}

int fun()
{
struct foo_vars_s o[1];
< local var ref x is replaced by o->x below >

...
if (<condition1>) return cleanup(1, o);

< normal processing 1 >

...

if (<condition2>) return cleanup(2, o);

...
< normal processing 2>
... yada yada ...

return 0;
}

This isn't ideal either.
 
G

Gene

#define CLEANUP_AND_RETURN(N) do { \
<cleanup code> \
return (N); \
} while (0);

Sorry. The last semicolon above is wrong. This should have been

#define CLEANUP_AND_RETURN(N) do { \
<cleanup code> \
return (N); \
} while (0)

This trick of using a do { } while(0) wrapper allows macro invocation
to work as void function calls where a proper statement is expected,
e.g. in the "then" or "else" of an "if". First saw this in gcc
sources a long time ago.
 
K

Keith Thompson

Gene said:
Sorry. The last semicolon above is wrong. This should have been

#define CLEANUP_AND_RETURN(N) do { \
<cleanup code> \
return (N); \
} while (0)

This trick of using a do { } while(0) wrapper allows macro invocation
to work as void function calls where a proper statement is expected,
e.g. in the "then" or "else" of an "if". First saw this in gcc
sources a long time ago.

See also question 10.4 in the comp.lang.c FAQ, <http://www.c-faq.com/>.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top