Good practice of using void function return type?


D

dspfun

Hi,

What is a good practice of using void return type for functions?

Would a good utilization of a void function be to print a header/footer to a screen or file?

Is there some rule of thumb?

Brs
 
Ad

Advertisements

M

Malcolm McLean

What is a good practice of using void return type for functions?

Would a good utilization of a void function be to print a header/footer to a screen or file?

Is there some rule of thumb?
In C, it doesn't really matter.
If we want to return two values from a function, we must write

void getcursorxy(int *x, int *y).

If we want to return one value, normally we would write

int getcursorx();
int getcursory();

But if the values are of equal status in some logical sense, you might want
to write

double mode(double *x, int N, int *morethanonemode);

most people aren't going to handle the case where a distribution has more than
one mode, but a few might want to pick it up.

Some people use the convention that the return type is always an integer that is
zero when the function succeed and negative when it fails. So all returned values
are passed via pointers. Others use the convention that the last parameter is
a pinter to an error flag. You can argue about those.

With IO functions, it's always possible for the IO to fail due to some hardware
issue or limitation. In the case of printing text to the screen, it's so unlikely, and
so unlikely that the program can make any effective response, that it's probably
not worth even considering the possibility. In the case of writing to a file on a small
syste, the disk could easily run out of space, and it's probably quite easy to ask
the user to free up some pace by deleting a file. So you might want to return an
error and handle it.
 
D

dspfun

Den torsdagen den 15:e maj 2014 kl. 12:33:43 UTC+2 skrev Malcolm McLean:
In C, it doesn't really matter.

If we want to return two values from a function, we must write



void getcursorxy(int *x, int *y).



If we want to return one value, normally we would write



int getcursorx();

int getcursory();



But if the values are of equal status in some logical sense, you might want

to write



double mode(double *x, int N, int *morethanonemode);



most people aren't going to handle the case where a distribution has more than

one mode, but a few might want to pick it up.



Some people use the convention that the return type is always an integer that is

zero when the function succeed and negative when it fails. So all returned values

are passed via pointers. Others use the convention that the last parameter is

a pinter to an error flag. You can argue about those.



With IO functions, it's always possible for the IO to fail due to some hardware

issue or limitation. In the case of printing text to the screen, it's so unlikely, and

so unlikely that the program can make any effective response, that it's probably

not worth even considering the possibility. In the case of writing to a file on a small

syste, the disk could easily run out of space, and it's probably quite easy to ask

the user to free up some pace by deleting a file. So you might want to return an

error and handle it.

Thank you for your answer!

What kind of strategy is good with respect to checking if a function call was successful or not?

When writing new functions, is it good practice to always have a return value which indicates if the function call completed successfully or not? This would mean that void return type should never be used.

Should the return value of a function call always be checked to see if it the function call completed successfully or not?
 
S

Stefan Ram

dspfun said:
Would a good utilization of a void function be to print a header/footer to a screen or file?

One does not start wanting to »utilize« functions. Instead
one starts wanting to solve a particular problem, such as
writing an FFT analyzer for certain signals. One uses a
development method to plan a program structure, which is a
decomposition of the program into functions. The return type
of functions then is a by-product of this development process.
 
J

James Kuyper

Hi,

What is a good practice of using void return type for functions?

Would a good utilization of a void function be to print a header/footer to a screen or file?

Is there some rule of thumb?

A function can receive information from it's caller though its
arguments, and it can return information to it's caller though it's
return value and through it's arguments that have pointer-to-non-const
type. I prefer using the return value, as long as the information that
needs to be returned has a scalar or struct type. That's because it's
slightly easier to do so than by returning the information through a
pointer argument. However, if a function already needs to have a pointer
arguments for other reasons, that happen to be suitable for returning
all of the needed information, then you should declare it as returning void.

Any function that can fail (which in my experience, is the overwhelming
majority of functions) should return some information about why it
failed to the caller, so the caller has the option of using that
information to decide what to do about the failure. For historical
reasons, many C standard library functions report errors though the
errno mechanism, but that's come to be recognized as a bad idea. I've
found it convenient to reserve the function's return value for this
purpose, so void functions are pretty rare in my code.

I use the return value for other purposes only if doing so doesn't
interfere with the primary purpose of reporting errors. For instance, a
function that returns a pointer can report failure by returning a null
pointer - but this is acceptable only if there's no need to distinguish
different failure modes. A function that returns a floating point value
can return a NaN to report failure (but only on systems that support
quiet NaNs). A function that always returns a non-negative value when
things go right, can use a negative value to indicate failure.
 
M

Malcolm McLean

Den torsdagen den 15:e maj 2014 kl. 12:33:43 UTC+2 skrev Malcolm McLean:

What kind of strategy is good with respect to checking if a function call was successful or not?
There are two sorts of functions, function that do IO, and functions that shuffle bits about
in the computer memory. (In normal English usage, the first are "procedures", the second "functions",
but C calls both "functions", because the compiler isn't set up to make a rigorous distinction
between them.
Now an IO function can always fail if the IO device fails in some way.
A bit shuffling function can only fail if there is an internal programming error, if there is an external
programming error (it's called with invalid arguments), or if it runs out of memory - a call to
malloc() return null.
If there's a programming error, there's no correct behaviour, by definition. So what you do depends
on the stage of development and the environment - are wrong results better or worse than no
results? If you're programming a video game, probably just accept the error and hope that the
player doesn't notice a glitch. If you're programming a life support system, is shutting down the
program more or less catastrophic than blowing a fuse?

However there's a special case. A parser type function. This fails if fed invalid syntax, which might
well be a programming error. But often checking that the input is valid is almost as difficult as
writing the parser itself. So you generally need to consider parse errors specially.
When writing new functions, is it good practice to always have a return value which indicates
if the function call completed successfully or not? This would mean that void return type
should never be used.
It doesn't matter much whether you return an error flag with return error_status; or set a
passed-in error flag with *error = error_status. I tend to prefer the second, but that's just
my own style.
If the function can fail, it makes sense to report that to the caller. What if it's a bit-shuffling
function that doesn't allocate any memory? You could argue that you should return an error
which is always 0, so that if you change the internals for some reason you can expand it.
Other people would say that the extra clutter in the interface isn't worth it.
Should the return value of a function call always be checked to see if it the function call
completed successfully or not?
No, because you can't always handle an error sensibly. Sometimes errors are so unlikely that
there's a much higher chance that the computer will break, then you've got to ask if it's
worth checking the error.
A practical consideration is that C doesn't have exceptions. If every call is followed by an
error check, the error checks dominate the visual layout of the code, and it becomes hard
to see if the non-error logic flow is correct.
 
Ad

Advertisements

B

BartC

When writing new functions, is it good practice to always have a return
value which indicates if the function call completed successfully or not?
This would mean that void return type should never be used.

Some languages distinguish between functions which return values, and
procedures which don't.

Many programs will become utterly impossible to write and to read if every
procedure endeavoured to return a status code, and every call to that
procedure checked it!

A lot of the time a return value is meaningless. Or the procedure will deal
with the error internally. Or any error condition is signalled in other ways
(through globals, or via a parameter).
Should the return value of a function call always be checked to see if it
the function call completed successfully or not?

C's printf() returns a value (the number of characters written); how many
times do you check that?

Some return values must be checked if it means it is impossible to proceed
if there was a failure. But not all.
 
M

Malcolm McLean

Some return values must be checked if it means it is impossible to proceed
if there was a failure. But not all.
It's the the way round, surely.

If we can cope with the error, correct or suppress the situation, and proceed,
check the error. If there's nothing you can do, you can call exit() or you can
crash, and whilst the first is a bit neater, in most situations it won't make
any practical difference.
 
K

Kenny McCormack

C's printf() returns a value (the number of characters written); how many
times do you check that?

Some return values must be checked if it means it is impossible to proceed
if there was a failure. But not all.[/QUOTE]

I like the way the shell works when you have "set -e": all errors are fatal
unless you check for them. That's a good way to retain the system's
ability to check for catastrophic (unexpected) errors without requiring the
programmer to check the result of each and every call (such as printf,
which "never" fails).
 
K

Keith Thompson

Malcolm McLean said:
There are two sorts of functions, function that do IO, and functions
that shuffle bits about in the computer memory. (In normal English
usage, the first are "procedures", the second "functions", but C calls
both "functions", because the compiler isn't set up to make a rigorous
distinction between them.

In languages that distinguish between procedures and functions
(Pascal, Ada, etc.), a procedure is a subroutine that doesn't return
a value, and a function is a subroutine that does return a value.
Ada uses the term "subprogram" to emcompass both.

In C, the equivalent of a "procedure" is a function with a void
return type. The distinction is there; C just doesn't use the same
syntax to express it. (Note that C, unlike those other languages,
doesn't have a "function" keyword.)

I have never heard of the terms "function" and "procedure" being
used to distinguish between subroutines that do I/O and subroutines
that don't.

Can you cite an independent source that uses the words in that way?
 
K

Keith Thompson

Malcolm McLean said:
It's the the way round, surely.

If we can cope with the error, correct or suppress the situation, and
proceed, check the error. If there's nothing you can do, you can call
exit() or you can crash, and whilst the first is a bit neater, in most
situations it won't make any practical difference.

But you still need to check the return value to decide whether to
terminate the program.
 
Ad

Advertisements

K

Kenny McCormack

Keith Thompson said:
I have never heard of the terms "function" and "procedure" being
used to distinguish between subroutines that do I/O and subroutines
that don't.

Now you have. Progress.
Can you cite an independent source that uses the words in that way?

Uh oh. Another failing grade from Headmaster Kiki.

--
Modern Christian: Someone who can take time out from
complaining about "welfare mothers popping out babies we
have to feed" to complain about welfare mothers getting
abortions that PREVENT more babies to be raised at public
expense.
 
M

Malcolm McLean

I have never heard of the terms "function" and "procedure" being
used to distinguish between subroutines that do I/O and subroutines
that don't.

Can you cite an independent source that uses the words in that way?

From the dictionary:

function
A variable so related to another that for each value assumed by one there is a value determined for the other.

procedure
A process is a set or series of actions directed to some end or a natural series of changes; a procedure is a series of actions conducted in a certain manner, an established way of doing something.

So a function returns one set of values given another set of values, a procedure performs a series
of actions. Very simple, normal use of these words.
 
M

Malcolm McLean

But you still need to check the return value to decide whether to
terminate the program.
When a program's internal state is corrupted it's almost always catastrophic.
But occasionally it won't crash out, agreed.
 
J

James Kuyper

Many programs will become utterly impossible to write and to read if every
procedure endeavoured to return a status code, and every call to that
procedure checked it!

I actually work under coding guidelines that call for me write code
exactly that way: my own functions are supposed to return a status code
if they're capable of failing, and anytime my code calls a function
that's capable of reporting failure (by any method, not just by it's
return value), my code is supposed to check for that possibility and
take appropriate action if it occurs (what constitutes "appropriate
action" is for me to decide, but choosing "ignore it" is contrary to the
spirit of the guidelines). They're just guidelines, I'm free to ignore
them, but I consider them reasonable, and therefore do follow them. I
haven't found it impossible to either write or read such code (though it
does sometime get tedious). I've found it a lot easier to debug code
that's written that way.
A lot of the time a return value is meaningless.

I've only rarely seen anything like that. The only example I can think
of was a procedure which was incapable of failing, but was defined as
returning a code to indicate whether or not it had succeeded. I changed
it to be a void function.

I have seen functions that return a value that I don't need to know
(such as your printf() case below), but that's different from the value
being meaningless. I can imagine cases where it would be important to
know the value returned by printf(), though the issue has never come up
for me. In most cases, feof(stdout) and ferror(stdout) cover everything
I need to know.
... Or the procedure will deal
with the error internally. ...

A problem that can be dealt with completely internally is not a problem
that needs to be reported to the caller.
 
J

Joe Pfeiffer

Malcolm McLean said:
From the dictionary:

function
A variable so related to another that for each value assumed by one there is a value determined for the other.

procedure
A process is a set or series of actions directed to some end or a natural series of changes; a procedure is a series of actions conducted in a certain manner, an established way of doing something.

So a function returns one set of values given another set of values, a procedure performs a series
of actions. Very simple, normal use of these words.

What on earth dictionary provided those definitions? The definition of
function is simply bizarre, and the second (a) is the general,
non-computer use of the term, and (b) doesn't support your contention
that procedures do I/O.
 
Ad

Advertisements

B

BartC

James Kuyper said:
I actually work under coding guidelines that call for me write code
exactly that way: my own functions are supposed to return a status code
if they're capable of failing, and anytime my code calls a function
that's capable of reporting failure (by any method, not just by it's
return value), my code is supposed to check for that possibility and
take appropriate action if it occurs (what constitutes "appropriate
action" is for me to decide, but choosing "ignore it" is contrary to the
spirit of the guidelines). They're just guidelines, I'm free to ignore
them, but I consider them reasonable, and therefore do follow them. I
haven't found it impossible to either write or read such code (though it
does sometime get tedious). I've found it a lot easier to debug code
that's written that way.

I've only rarely seen anything like that.

A lot of the time a function will just contain a sequence of statements.
Perhaps to break up a larger one or just to give some structure.

Would you do a status check every half-dozen statements? No, so why is it
necessary when you wrap a function body around the same statements?

(And what on earth would you check anyway, that the right-hand-side of an
assignment was successfully copied to the left side? Would you then also
have to check that the check was done properly? Etc.)

Some functions will have return values; and some won't (and I deliberately
call them procedures to make it completely clear). And some of the return
values will be statuses that ought to be checked.
A problem that can be dealt with completely internally is not a problem
that needs to be reported to the caller.

So that's another example where no value need be returned.
 
M

Malcolm McLean

What on earth dictionary provided those definitions? The definition of
function is simply bizarre, and the second (a) is the general,
non-computer use of the term, and (b) doesn't support your contention
that procedures do I/O.
I just did Google searches on "define".

A function is a mapping of a set of values to another set of values. It can be "undefined"
for some sets of inputs (e.g. 0/0), so the definition is hardly rigourous, but it's good
enough for general use.

"Procedure" isn't a technical term at all. Every native English speaker knows what a
procedure is. There's no particular reason to use it in a special sense in computer
science, just because a few languages use the term in their jargon.
 
M

Malcolm McLean

The first is the approximately usual mathematical definition of a
function. But if you're going to go that route a "variable" in
mathematics isn't what we call a variable in programming either.
Neither is an appropriate definition to use when talking about
programming (except in a sentence like "Functions and variables in
programming are not like the concepts of the same name in
mathematics").
A function shuffles bits about in memory, a procedure activates an
external device attached to the computer.
What's wrong, illogical, or extraordinary about that? It's just
using the normal English words to make a distinction that anyone
could see is likely to be meaningful.
 
Ad

Advertisements

G

glen herrmannsfeldt

(snip)
In languages that distinguish between procedures and functions
(Pascal, Ada, etc.), a procedure is a subroutine that doesn't return
a value, and a function is a subroutine that does return a value.
Ada uses the term "subprogram" to emcompass both.

And in PL/I, they are all procedures (abbreviatable to PROC).
In C, the equivalent of a "procedure" is a function with a void
return type. The distinction is there; C just doesn't use the same
syntax to express it. (Note that C, unlike those other languages,
doesn't have a "function" keyword.)

As far as I know, Fortran originated the FUNCTION keyword.
I have never heard of the terms "function" and "procedure" being
used to distinguish between subroutines that do I/O and subroutines
that don't.

I don't know specifically about I/O, but Fortran has PURE, and PURE
functions and subroutines can't do I/O, or anything else that would
allow saving state. They can't even STOP!
Can you cite an independent source that uses the words in that way?

-- glen
 

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

Top