Redundant return()

P

pembed2012

I have seen redundant return statements at the end of function. IE.
init_function()
{
a_init();
b_init();
c_init();
return();
}
I checked the generated code in GCC Compiler 3.2.2 on Red Hat Linux it
is ignored so it not harmful to use this.

Has anybody got any problem/issues with this on any compiler/platform?
 
S

Stefan Ram

pembed2012 said:
I have seen redundant return statements at the end of function. IE.
init_function()
{
a_init();
b_init();
c_init();
return();
}

There is no return statement above.

i.e. = id est (that is)
IE = internet explorer
 
J

James Kuyper

I have seen redundant return statements at the end of function. IE.
init_function()
{
a_init();
b_init();
c_init();
return();
}
I checked the generated code in GCC Compiler 3.2.2 on Red Hat Linux it
is ignored so it not harmful to use this.

Has anybody got any problem/issues with this on any compiler/platform?

I wouldn't use a "return;" where it wasn't needed, for the same reason I
wouldn't use parentheses in a place where they aren't needed, such as
"return();". However, they should never cause any actual problems.
 
B

Barry Schwarz

I have seen redundant return statements at the end of function. IE.
init_function()
{
a_init();
b_init();
c_init();
return();

ITYM return;
}
I checked the generated code in GCC Compiler 3.2.2 on Red Hat Linux it
is ignored so it not harmful to use this.

Has anybody got any problem/issues with this on any compiler/platform?

Some organizations have coding standards which require each function
to have exactly one explicit return at the end of the function. It
simplifies maintenance if the type or presence of a return value needs
to be changed during a software update.

I wonder what kind of problem you envision. At worst, a brain dead
compiler could generate instructions for the return statement and then
a second set of (duplicate?) instructions for the implied return at
the closing brace.
 
J

Joe Pfeiffer

pembed2012 said:
sorry function shall be a VOID function :)

Well... no problem with the explicit return (I'm pretty sloppy about
whether I use them or not), but there is a problem with your example
(just to be sure, I checked and here's what gcc told me):

bogus.c:13:12: error: expected expression before ‘)’ token
bogus.c:13:5: warning: ‘return’ with a value, in function returning void [enabled by default]
 
E

Eric Sosman

I wouldn't use a "return;" where it wasn't needed, for the same reason I
wouldn't use parentheses in a place where they aren't needed, such as
"return();". However, they should never cause any actual problems.

Section 6.4.1 lists `return' as a keyword, so it cannot be
an identifier. Nor, by omission from other sections, can it be
an operator. 6.8.6 describes the only valid context for the
keyword, giving it as (ASCII adaptation)

return expression[opt] ;

Since `()' matches neither `expression' nor `absence of expression',
it follows that `return();' is a syntax error requiring a diagnostic.

... but other than that, Mrs. Lincoln, there are no actual
problems.
 
J

James Kuyper

I wouldn't use a "return;" where it wasn't needed, for the same reason I
wouldn't use parentheses in a place where they aren't needed, such as
"return();". However, they should never cause any actual problems.

Section 6.4.1 lists `return' as a keyword, so it cannot be
an identifier. Nor, by omission from other sections, can it be
an operator. 6.8.6 describes the only valid context for the
keyword, giving it as (ASCII adaptation)

return expression[opt] ;

Since `()' matches neither `expression' nor `absence of expression',
it follows that `return();' is a syntax error requiring a diagnostic.

You're right, I missed that. His question focused me on the redundancy
of the return statement, rather than whether it was syntactically correct.
-
James Kuyper
 
P

pembed2012

ITYM return;


Some organizations have coding standards which require each function to
have exactly one explicit return at the end of the function. It
simplifies maintenance if the type or presence of a return value needs
to be changed during a software update.

I wonder what kind of problem you envision. At worst, a brain dead
compiler could generate instructions for the return statement and then a
second set of (duplicate?) instructions for the implied return at the
closing brace.

Ho, you are right, I can invoke the return function with no () and there
is no compiler error. Wired.

I thought in a VOID function it will be an error to invoke return, maybe
clobber the place in the stack that would store a return val in a non-
VOID function etc.
 
B

Ben Bacarisse

pembed2012 said:
Ho, you are right, I can invoke the return function with no () and there
is no compiler error. Wired.

It's not a function -- it's a statement, and using empty brackets is
*always* wrong. What's more you don't need the brackets even when there
is an expression. Both

return;

and

return 42;

are valid, though it's a mistake to use the first form in a function
that has non-void return type or to use the second form in a function
that is declared "void".
I thought in a VOID function it will be an error to invoke return, maybe
clobber the place in the stack that would store a return val in a non-
VOID function etc.

No, it's fine. You can have any number of return statement in a "void"
function -- provided you don't try to return a value.
 
G

Guest

On Monday, May 14, 2012 5:40:34 PM UTC+1, pembed2012 wrote:

Ho, you are right, I can invoke the return function with no () and there
is no compiler error. Wired.

as others have pointed out "return IS NOT a function!"
I thought in a VOID function it will be an error to invoke return, maybe
clobber the place in the stack that would store a return val in a non-
VOID function etc.

some odd misconceptions. An early return can be handy. Though som people (not me) dislike it for reasons of style

void writeLog (FILE *log, const char *msg)
{
if (log == NULL)
return;

/* complex processing */
fprintf (log, "LOG: %s %s\n", timestamp(), msg);
}
 
S

Stefan Ram

The supposed spelling is »wierd«.

some odd misconceptions. An early return can be handy.

»handy« is vague wording.
if (log == NULL)
return;
/* complex processing */

If it is complex, we put it into a function »f«, so:

if( log ){ f(); fprintf( log, "LOG: %s\n", msg ); }

. The real reason for an early return as in

while( ... )
{ ...
if( ... )return result;
... }

is that tests have shown that this often executes faster
than a single exit.
 
G

Guest

The supposed spelling is »wierd«.

"supposed spelling"? Not "correct spelling"?

I must admit i just assumed he was on drugs. :)
»handy« is vague wording.

yes it is. That's why I gave an example of an early return.
If it is complex, we put it into a function »f«, so:

if( log ){ f(); fprintf( log, "LOG: %s\n", msg ); }

why? My code was clear and easy to understand. This is just single-exit bigotry.
. The real reason for an early return as in

"real"? Why is this any more "real" than any other reason? What you meant to say is "another reason"
while( ... )
{ ...
if( ... )return result;
... }

is that tests have shown that this often executes faster
than a single exit.

"often"? On all architectures? At all optimisation levels? How much faster? this is micro-optimisation (at best); something we normal discourage newbies from indulging in.

I submit my usage of early return, to detect special cases early on and avoid deep nesting, is more "real" than your obscure micro-optimisation trick.
 
S

Stefan Ram

why? My code was clear and easy to understand.

Assume, you had complex code:

...
... return ...
...
... return ...
... return ...
...
...
... return ...
...
... return ...
... return ...
...

The many returns hinder extract-function refactoring,
because, when you want to extract the first half of this
into a separate function, the returns now jump to the end of
that new function, which usually is not what they are
supposed to do, so one has to do a more complex and
error-prone rewriting during this refactor.

When a block has a single entry and exit, the
extract-function refactor is usually easy.

This could be a reason that complex code such as
above is not refactored, so that it will be harder
to maintain.
"real"? Why is this any more "real" than any other reason?

It is the only excuse that I accept for the use of multiple
returns in a function.
 
G

Guest

like I said in a bit of my post you snipped. This is a style thing. Some people like to jump through hoops to give single-entry-single-exit properties to their code. Some don't. I simply object to you stating it as if it were some sort of Programming Law.
Assume, you had complex code:

...
... return ...
...
... return ...
... return ...
...
...
... return ...
...
... return ...
... return ...
...

I don't usually write code that is as complicated as that.
The many returns hinder extract-function refactoring,

haven't noticed a problem.
because, when you want to extract the first half of this
into a separate function, the returns now jump to the end of
that new function, which usually is not what they are
supposed to do, so one has to do a more complex and
error-prone rewriting during this refactor.

When a block has a single entry and exit, the
extract-function refactor is usually easy.

This could be a reason that complex code such as
above is not refactored, so that it will be harder
to maintain.


It is the only excuse that I accept for the use of multiple
returns in a function.

whatever
 
B

BartC

Stefan Ram said:
The supposed spelling is »wierd«.



»handy« is vague wording.


If it is complex, we put it into a function »f«, so:

if( log ){ f(); fprintf( log, "LOG: %s\n", msg ); }

This is crazy. The effect is to create an extra function (the current one)
which contains just a single statement, more or less.

If the return was half-way through the function, you'd then be splitting it
into two for probably no reason, and would have the headache of making all
the locals which have been used and set up, available to the new function.
If it is complex, we put it into a function »f«, so:

But the body of f() will still be complex (as you've only eliminated a
couple of lines; it that now makes it simple, then it was *not* complex!);
then what? Suppose there were several such returns in a function? You would
end up *increasing* complexity (by extra functions, extra names, extra
interfaces) for no discernible benefit. Actually it would be probably be
slower, less readable, and more buggy.
 
J

James Kuyper

The supposed spelling is �wierd�.



�handy� is vague wording.


If it is complex, we put it into a function �f�, so:

if( log ){ f(); fprintf( log, "LOG: %s\n", msg ); }

. The real reason for an early return as in

while( ... )
{ ...
if( ... )return result;
... }

is that tests have shown that this often executes faster
than a single exit.

Any decent modern compiler should generate the same code either way, so
if it does run noticeably faster using one approach, then you should get
a better compiler.

The relevant issue isn't speed, but ease of comprehension. Supporters of
"single exit" claim it's easier to comprehend; my personal experience is
that early-return is easier.
 
J

James Kuyper

Assume, you had complex code:

...
... return ...
...
... return ...
... return ...
...
...
... return ...
...
... return ...
... return ...
...

The many returns hinder extract-function refactoring,
because, when you want to extract the first half of this
into a separate function, the returns now jump to the end of
that new function, which usually is not what they are
supposed to do, so one has to do a more complex and
error-prone rewriting during this refactor.

When a block has a single entry and exit, the
extract-function refactor is usually easy.

In my personal experience, early returns usually correspond to error
conditions, so jumping to the end of the new function is usually what I
want them to do.
 
I

Ian Collins

But the body of f() will still be complex (as you've only eliminated a
couple of lines; it that now makes it simple, then it was *not* complex!);
then what? Suppose there were several such returns in a function? You would
end up *increasing* complexity (by extra functions, extra names, extra
interfaces) for no discernible benefit. Actually it would be probably be
slower, less readable, and more buggy.

Testing. A large, complex, function is hard to test. More less complex
functions are easier to test. That's why code written test first won't
contain large, complex, functions.
 

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

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top