void func () returning value?

W

William Hughes

Andrey said:
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.

Changing a typedef is a *very* dangerous thing to do. Unless the
change is fairly minor (e.g. one int width to another) and/or planned
on when designing the code, it is likely to lead to disaster.
Even at the best of times it is hardly "safe".

Changing a return value from non-void to void is so likely to
cause disaster that I would never do it, unless I had designed
my code to allow this from the start (In which case I would
have to turn handsprings to allow myself to use the possible
return value safely.)

This is not a good argument for allowing void functions
to return a parameter of type void.

- William Hughes
 
Y

Yevgen Muntyan

Richard said:
Tastes differ. I find it horrible.

This is totally fine.
You're using a single statement to do
two things which are not related to one another.

Exactly the same can be said about "return non_void_func();"
(actually, this case is even more about two things - it also
returns value). Do you find

int foo1 (int a)
{
return a + 8;
}

int foo (int a)
{
if (a < 0)
return foo1 (-a);
else
return 8;
}

also terrible? If your answer is "yes", then we are talking about
a bit different things: you don't like some practice allowed by
standard and used a lot in real code, and I don't like standard
not allowing to use this practice in uniform way regardless of
function return value. If your answer is "no", then you'd need
to explain how "return value();" is one thing and "return void_func();"
is "two things".
That's not good
practice, and it's not efficient (in fact, it's likely to throw some
optimisers off the scent);

Maybe, does it matter (the efficiency part)? How much worse is it? Or,
in what/how many cases "return void_func();" affects program
performance, amount of memory it consumes, or whatever else is meant by
"efficient".

Best regards,
Yevgen
 
A

Andrey Tarasevich

William said:
...
Changing a typedef is a *very* dangerous thing to do. Unless the
change is fairly minor (e.g. one int width to another) and/or planned
on when designing the code, it is likely to lead to disaster.
Even at the best of times it is hardly "safe".

Changing a return value from non-void to void is so likely to
cause disaster that I would never do it, unless I had designed
my code to allow this from the start (In which case I would
have to turn handsprings to allow myself to use the possible
return value safely.)
...

This is the case when the "general case" arguments don't really apply. It all
depends on the typedef itself and why it was introduced in the first place (but
that is essentially what you are saying yourself). In generic code ("template"
code, if you will, which can actually be used in C, even though it doesn't
provide any C++-like template support) a typedef name might be introduced for
the very purpose of being easily changeable between a wide range of types.

And, firstly, in many cases there's no need to "turn handsprings" for that. And,
secondly, even if there is, it might be worth it.
...
This is not a good argument for allowing void functions
to return a parameter of type void.
...

Well, this is not a feature that can possibly have "good" arguments for or
against it. It is just one of those things that allows certain freedom of
personal preference. Some people never use 'do/while' cycles and believe theres'
no "good" argument for them to be in the language. I, for one, do use 'do/while'
cycles.
 
W

William Hughes

Andrey said:
This is the case when the "general case" arguments don't really apply. It all
depends on the typedef itself and why it was introduced in the first place (but
that is essentially what you are saying yourself). In generic code ("template"
code, if you will, which can actually be used in C, even though it doesn't
provide any C++-like template support) a typedef name might be introduced for
the very purpose of being easily changeable between a wide range of types.

Pehaps you could provide an example of what you mean?

- William Hughes
 
A

Andrey Tarasevich

William said:
Pehaps you could provide an example of what you mean?
...

Well, I can. But what's the purpose of doing that when, I'm afraid, I'll just
get a bunch of replies stating that the same can be done with a separate
function-call statement and return statement? (Which, of course, I know and
which, of course, is completely beside the point).
 
R

Richard Harter

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.

Why on Earth should it be any less efficient?

I disagree that the two things are unrelated. When you invoke a
function as the argument in a return statement (not quite the right
wording but I trust that you know what I mean) it establishes that the
invoked function is an epilog, i.e., the very last thing that is done
before actually returning control to the parent function.

It's similar to using
a++;
instead of
a = a+1;

In each case you are using one form to force to things to happen
together. In the first case you are calling a function and returning
its result; in the second case you adding one to the value of a
variable and storing it in the variable. In each case you are
eliminating degrees of freedom. The general cases are:

a = foo();
return b;

b = a+1;

One degree of freedom disappears when b and a are identical, i.e.,

a = foo();
return a;

a = a+1;

So we have a special case where a degree of freedom is missing but the
form doesn't make that obvious; this creates a potential source of
error. There is a (rather small?) advantage to using a form that
reflects that actual number of degrees of freedom, e.g.,

return foo();

a++;

All of that said, the whole thing is a bit of a tempest in a teapot.
 
W

William Hughes

Andrey said:
Well, I can. But what's the purpose of doing that when, I'm afraid, I'll just
get a bunch of replies stating that the same can be done with a separate
function-call statement and return statement? (Which, of course, I know and
which, of course, is completely beside the point).

Not completely. You argue that the ability of void functions to return
void
functions should be added to the C language. Unless you want to argue
that
this looks prettier (in which case "De gustibus non est disputandum"
holds,
with the proviso that making any change to the language is not cost
free
even when a new standard is being brought out) you need to show an
example where the separate function call and return statement would
be impossible or less elegant. You have claimed that such a situation
would arise in "template like" code, but have not given an example.
If indeed, as you suggest, the single return statement can be replaced
by separate function call and return statements even in "template like
code", your argument that it was an error to leave this out of C99 is
weak.
- William Hughes
 
R

Richard Bos

Yevgen Muntyan said:
Exactly the same can be said about "return non_void_func();"
(actually, this case is even more about two things - it also
returns value).

Yes, but those things are related. You compute a value, and then you
return _that_ value. In the void case, you perform a function which does
not deliver any value, and then you return. There is no relation between
the performed function and the return from the calling function, unlike
in the non-void case, where that relation is the computed value.

Richard
 
Y

Yevgen Muntyan

Richard said:
Yes, but those things are related. You compute a value, and then you
return _that_ value. In the void case, you perform a function which does
not deliver any value, and then you return. There is no relation between
the performed function and the return from the calling function, unlike
in the non-void case, where that relation is the computed value.

Well, "val = func(); return val;" does exactly same thing as "return
func();", still they are different. The "you perform a function which
does not deliver any value, and then you return" is correct but not
quite, it's more "you perform a function, and then you return
*immediately*".

Consider this:

=============================
void func (int *in_arg)
{
...
}

void func2 (int *in_arg)
{
return func (in_arg);
}
=============================

and

=============================
int func (int arg)
{
...
}

int func2 (int arg)
{
return func (arg);
}
=============================

There is no return value in the first case; but in both cases
the "return func();" do exactly same thing - they transfer control
to func(); it's kind of "goto func".

Best regards,
Yevgen
 

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,789
Messages
2,569,634
Members
45,342
Latest member
Sicuro

Latest Threads

Top