Good practice of using void function return type?

Discussion in 'C Programming' started by dspfun, May 15, 2014.

  1. dspfun

    dspfun Guest

    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
     
    dspfun, May 15, 2014
    #1
    1. Advertisements

  2. 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.
     
    Malcolm McLean, May 15, 2014
    #2
    1. Advertisements

  3. dspfun

    dspfun Guest

    Den torsdagen den 15:e maj 2014 kl. 12:33:43 UTC+2 skrev Malcolm McLean:
    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?
     
    dspfun, May 15, 2014
    #3
  4. dspfun

    Stefan Ram Guest

    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.
     
    Stefan Ram, May 15, 2014
    #4
  5. dspfun

    James Kuyper Guest

    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.
     
    James Kuyper, May 15, 2014
    #5
  6. 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.
    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.
    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.
     
    Malcolm McLean, May 15, 2014
    #6
  7. dspfun

    BartC Guest

    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).
    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.
     
    BartC, May 15, 2014
    #7
  8. 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.
     
    Malcolm McLean, May 15, 2014
    #8
  9. 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).
     
    Kenny McCormack, May 15, 2014
    #9
  10. 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?
     
    Keith Thompson, May 15, 2014
    #10
  11. But you still need to check the return value to decide whether to
    terminate the program.
     
    Keith Thompson, May 15, 2014
    #11
  12. Now you have. Progress.
    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.
     
    Kenny McCormack, May 15, 2014
    #12
  13. 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.
     
    Malcolm McLean, May 15, 2014
    #13
  14. When a program's internal state is corrupted it's almost always catastrophic.
    But occasionally it won't crash out, agreed.
     
    Malcolm McLean, May 15, 2014
    #14
  15. dspfun

    James Kuyper Guest

    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. 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.
    A problem that can be dealt with completely internally is not a problem
    that needs to be reported to the caller.
     
    James Kuyper, May 15, 2014
    #15
  16. dspfun

    Joe Pfeiffer Guest

    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.
     
    Joe Pfeiffer, May 15, 2014
    #16
  17. dspfun

    BartC Guest

    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.
    So that's another example where no value need be returned.
     
    BartC, May 15, 2014
    #17
  18. 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.
     
    Malcolm McLean, May 15, 2014
    #18
  19. 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.
     
    Malcolm McLean, May 15, 2014
    #19
  20. (snip)
    And in PL/I, they are all procedures (abbreviatable to PROC).
    As far as I know, Fortran originated the FUNCTION keyword.
    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!
    -- glen
     
    glen herrmannsfeldt, May 15, 2014
    #20
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.