void func () returning value?

Y

Yevgen Muntyan

Hey,

Consider the following code:

void func (void)
{
}

void func2 (void)
{
return func ();
}

gcc -pedantic says the following:

muntyan@munt10:/tmp$ gcc -pedantic -c file.c
file.c: In function ‘func2’:
file.c:7: warning: ‘return’ with a value, in function returning void

If I recall correctly, compiler in some Microsoft Visual Studio version
told me the same thing. So, is this a compiler bug (feature), or is this
"return func ();" invalid in standard C?

Thanks,
Yevgen
 
G

Guest

Yevgen said:
Hey,

Consider the following code:

void func (void)
{
}

void func2 (void)
{
return func ();
}

gcc -pedantic says the following:

muntyan@munt10:/tmp$ gcc -pedantic -c file.c
file.c: In function ‘func2’:
file.c:7: warning: ‘return’ with a value, in function returning void

If I recall correctly, compiler in some Microsoft Visual Studio version
told me the same thing. So, is this a compiler bug (feature), or is this
"return func ();" invalid in standard C?

It's invalid in standard C. Perhaps you're thinking of C++, where it is
allowed?
 
N

Nick Keighley

Harald said:
Yevgen Muntyan wrote:

It's invalid in standard C. Perhaps you're thinking of C++, where it is
allowed?

since when has it been valid for a void function to return a value, in
either C or C++?
 
G

Greg

Nick said:
since when has it been valid for a void function to return a value, in
either C or C++?

It's not legal in C++ for a "return" statement of a void function to
return a value [§6.6.3]. The above program is nonetheless OK since it
is legal in C++ for a return statement in a void function to have a
(cv) void type expression - as in this case, the return expression is
simply a call to another void function.

Greg
 
R

Risto Lankinen

since when has it been valid for a void function to return a value, in
either C or C++?

A void function can "return" an expression whose type is void . This
is to facilitate templates such as...

template <typename T> T func() { return static_cast<T>(expr); }

.... to be instantiable also for T=void.

- Risto -
 
Y

Yevgen Muntyan

Harald said:
It's invalid in standard C. Perhaps you're thinking of C++, where it is
allowed?

I am sure I was thinking about C :)
After comparing C and C++ standards it looks like it's a useful C++
feature which wasn't backported to C standard. I thought it was
natural to do 'return func()' for func() returning nothing, but
now I'm curious if there are other languages where it's valid
(I could swear it's so in one of languages I know and where function
can really return nothing, but it's not the case).

Best regards,
Yevgen
 
M

mark_bluemel

Yevgen said:
After comparing C and C++ standards it looks like it's a useful C++
feature which wasn't backported to C standard.

For some value of "useful"...

BTW: are you implying that C is, or should be, a subset of C++?
That would, I suspect, be "fighting talk" :)
I thought it was
natural to do 'return func()' for func() returning nothing,

I thought it was unnatural - funny how people's interpretation of
"natural" varies...
 
Y

Yevgen Muntyan

Yevgen Muntyan wrote:




For some value of "useful"...

void foo (void)
{
...
for (i = 0; i < 42; ++i)
if (bar (i))
return simple_foo (i);
real_foo_here();
}

Using two statements (function call and return) makes it lot
uglier for me - bunch of curly brackets added. Not a real problem,
of course, but I find "return void_func();" very nice.
BTW: are you implying that C is, or should be, a subset of C++?
That would, I suspect, be "fighting talk" :)

No, of course no, I think that C++ is a superset of C ;)
Seriously speaking, // comments are a (useful, I think) C++
feature "backported" to C, aren't they? I absolutely didn't mean
"C sucks because C++...." or "C++ is so much nicer because..."

Best regards,
Yevgen
 
M

mark_bluemel

Yevgen said:
void foo (void)
{
...
for (i = 0; i < 42; ++i)
if (bar (i))
return simple_foo (i);
real_foo_here();
}

Using two statements (function call and return) makes it lot
uglier for me - bunch of curly brackets added. Not a real problem,
of course, but I find "return void_func();" very nice.

As a predominantly maintenance programmer, I would immediately have
changed your code to

void foo (void)
{
...
for (i = 0; i < 42; ++i) {
if (bar (i)) {
return simple_foo (i);
}
}
real_foo_here();
}

for starters, so splitting function call and return into two lines is
not a big overhead. Leaving braces out is a recipe for future bugs
IMHO....

I stick to my opinion that "void foo()" means that "foo()" doesn't
return anything, so combining an arbitrary call to a void function with
the return is fairly stupid. If you wanted to call something and ignore
its result would you do (for example) 'return (void)printf("My Dog Has
Fleas\n");' ?

As for "//" for comments, I'm rather inclined to prefer "/* ... */" but
that's a personal thing, I guess
 
F

Fred Kleinschmidt

As a predominantly maintenance programmer, I would immediately have
changed your code to

void foo (void)
{
...
for (i = 0; i < 42; ++i) {
if (bar (i)) {
return simple_foo (i);
}
}
real_foo_here();
}

for starters, so splitting function call and return into two lines is
not a big overhead. Leaving braces out is a recipe for future bugs
IMHO....

I stick to my opinion that "void foo()" means that "foo()" doesn't
return anything, so combining an arbitrary call to a void function with
the return is fairly stupid. If you wanted to call something and ignore
its result would you do (for example) 'return (void)printf("My Dog Has
Fleas\n");' ?

As for "//" for comments, I'm rather inclined to prefer "/* ... */" but
that's a personal thing, I guess

I would have changed it to:

void foo (void)
{
...
for (i = 0; i < 42; ++i) {
if (bar (i)) {
simple_foo (i);
return;
}
}
real_foo_here();
}

Think what would happen if simple_foo() werre changed
to return a value (an error code, of perhaps something else
that foo() is not interested in). If you instead used
return simple_foo(i)
then suddenly the program would not compile.

Now, this may or may not be a reasonable thing.
The compile error would certainly warn you that
perhaps you should pay attention to the return value
of the modified simple_foo() function.
 
A

Al Balmer

I am sure I was thinking about C :)
After comparing C and C++ standards it looks like it's a useful C++
feature which wasn't backported to C standard.

In C, it's a trivial transformation to

func();
return;

What's useful about it? (Aside from possible use in obfuscation.)
 
R

Richard

Harald van Dijk said:
It's invalid in standard C. Perhaps you're thinking of C++, where it is
allowed?

It is also bad practice IMO.

When reading the code you would immediately assume that func()
is returning a required value.

I have also found in years of modifying large legacy code bases that
"return func()" is not as easy to monitor and debug as "rc= func();
return rc;". Admittedly a personal preference built up from my own
experiences.
 
E

Elijah Cardon

Richard said:
It is also bad practice IMO.

When reading the code you would immediately assume that func()
is returning a required value.

I have also found in years of modifying large legacy code bases that
"return func()" is not as easy to monitor and debug as "rc= func();
return rc;". Admittedly a personal preference built up from my own
experiences.
Why do people TRY to find bad logic scenarios with the C Programming
Language. You have two void functions and try to return a call to the first
in the second. If a compiler didn't scream, I would. EC
 
Y

Yevgen Muntyan

Fred said:
I would have changed it to:

void foo (void)
{
...
for (i = 0; i < 42; ++i) {
if (bar (i)) {
simple_foo (i);
return;
}
}
real_foo_here();
}

Think what would happen if simple_foo() werre changed
to return a value (an error code, of perhaps something else
that foo() is not interested in). If you instead used
return simple_foo(i)
then suddenly the program would not compile.

Yes, exactly. Compiler will complain if either foo or simple_foo
change return value from void to something. And it is a really
good thing.

Regards,
Yevgen
 
Y

Yevgen Muntyan

Yevgen Muntyan wrote:




As a predominantly maintenance programmer, I would immediately have
changed your code to

void foo (void)
{
...
for (i = 0; i < 42; ++i) {
if (bar (i)) {
return simple_foo (i);
}
}
real_foo_here();
}
>
> for starters, so splitting function call and return into two lines is
> not a big overhead. Leaving braces out is a recipe for future bugs
> IMHO....
>

If I got this piece of code (with split return statement), I would
change it to:

void foo (void)
{
...
for (i = 0; i < 42; ++i)
{
if (bar (i))
{
simple_foo ();
return;
}
}
real_foo_here();
}

And *here* brackets are no good if you can do without them at all.
A nitpick/rationale: your coding style forces you to always use brackets
since you can't clearly see if there is an opening bracket, so closing
bracket alone is easily lost, and "Leaving braces out is a recipe for
future bugs". In mine, I can easily *see* that I need to add brackets if
I suddenly add a statement. Hope it will not start yet another flame
war on coding style ;)
I stick to my opinion that "void foo()" means that "foo()" doesn't
return anything, so combining an arbitrary call to a void function with
the return is fairly stupid. If you wanted to call something and ignore
its result would you do (for example) 'return (void)printf("My Dog Has
Fleas\n");' ?

No, I wouldn't. Because this cast hides return value, so it's dangerous.
In case with void-void compiler will warn me if some function changes
return type, so I'm safe.
As for "//" for comments, I'm rather inclined to prefer "/* ... */" but
that's a personal thing, I guess

Sure it is.

Best regards,
Yevgen
 
A

Andrey Tarasevich

...

I thought it was unnatural - funny how people's interpretation of
"natural" varies...
...

It is more about the ability to recognize "natural" where it is indeed present.
Someone already demonstrated an example of C++ template code that shows where
this feature can be extremely useful. However, it is absolutely unnecessary to
drag C++ and templates here for that purpose, because C language already has
everything necessary to achieve the level of generality that makes that feature
useful. The example follows

typedef int T;

T foo() { ... };
T bar() { return foo(); }
T baz() { return foo(); }


In at some point in the future I might decide to change the typedef to

typedef void T;

I'll have to comb through the entire program's source code and break all such
return statements into two lines. (And repeat the whole thing again when I
decide to change it back). That is heavily UNnatural. The support for "return
void" would solve the problem in a very elegant way.

So the feature in indeed objectively natural, but unfortunately it is not even
in C99.
 
Y

Yevgen Muntyan

Richard said:
It is also bad practice IMO.

When reading the code you would immediately assume that func()
is returning a required value.

Right, and required value in this case is "no value", at least
it's how I read it (and what gcc takes care of).
I have also found in years of modifying large legacy code bases that
"return func()" is not as easy to monitor and debug as "rc= func();
return rc;". Admittedly a personal preference built up from my own
experiences.

It's true, for stepping through the code in debugger split return
statement is better. But "return result_of_this_function_call();"
is so natural, and so easy to read, and doesn't require a dummy
"retval" variable; it's really a good thing. Even standard thinks
it's okay to do it :)

Regards,
Yevgen
 
A

Andrey Tarasevich

Richard said:
It is also bad practice IMO.

When reading the code you would immediately assume that func()
is returning a required value.
...

Well, it depends on how you look at it. I'd say it is actually a good practice
because in this case the code format emphasizes the intent to completely
delegate the flow to another function, in uniform fashion for both void and
non-void functions.
 
C

Christopher Benson-Manica

Andrey Tarasevich said:
typedef int T;
T foo() { ... };
T bar() { return foo(); }
T baz() { return foo(); }

In at some point in the future I might decide to change the typedef to
typedef void T;

In which case you're still SOL when it comes to the uses of bar() and
baz(), which probably look something like

if( bar() ) {
/* ... */
}

or

int quux;
/* ... */
quux = baz();
I'll have to comb through the entire program's source code and break all such
return statements into two lines. (And repeat the whole thing again when I
decide to change it back). That is heavily UNnatural. The support for "return
void" would solve the problem in a very elegant way.

It works a little bit more conveniently if you go from void to a real
type (since in that case bar() and baz() simply return a value that is
immediately discarded), but refactoring one or more functions to
return void when they previously returned a type is unlikely to be
helpful unless the return values were being ignored anyway, in which
case it was probably obvious that they should return void from the
beginning.
So the feature in indeed objectively natural, but unfortunately it is not even
in C99.

I don't really agree that it would be all that useful, unless you can
come up with a different example. I think the

return func_returning_void();

constructs that would thus be allowed would be confusing in any case,
so I can't say I'm sorry not to see this support in C99.
 
R

Richard Bos

Yevgen Muntyan said:
void foo (void)
{
...
for (i = 0; i < 42; ++i)
if (bar (i))
return simple_foo (i);
real_foo_here();
}

Using two statements (function call and return) makes it lot
uglier for me - bunch of curly brackets added. Not a real problem,
of course, but I find "return void_func();" very nice.

Tastes differ. I find it horrible. You're using a single statement to do
two things which are not related to one another. That's not good
practice, and it's not efficient (in fact, it's likely to throw some
optimisers off the scent); all it is is faux-hacker kewl.

Richard
 

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
473,774
Messages
2,569,598
Members
45,150
Latest member
MakersCBDReviews
Top