Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Functions and their return...

  1. Dec 30, 2015 #1
    Hello Forum,

    I am trying to get clear on the return statement when defining functions in C. A function is a group of statements that together perform a certain task. A function usually receives some input arguments which it uses to produce some output arguments. In C, we must specify what type of data the output is going to be. Some functions can possibly have no input arguments and no output arguments. For example, void main(void) receives and outputs nothing...I guess it simply initiates the code that it contains which could possibly produce inputs and outputs...

    In general, does the return statement represent/indicate the output of the function?

    Thanks,
    fog37
     
  2. jcsd
  3. Dec 30, 2015 #2
    At the assembler level, there is a specific register that you write the return value to. If the function doesn't return anything, you just don't write to the register.

    I wouldn't consider the value written to this register to be the exclusive output of the function. You may also write to other memory addresses or registers as well inside the function.
     
  4. Dec 30, 2015 #3
    What is one of the possible reasons to return something to a specific register in the CPU?
     
  5. Dec 30, 2015 #4

    FactChecker

    User Avatar
    Science Advisor
    Gold Member

    The returned value is placed in the position of the function call and can be easily used. You don't need to save it into a declared variable.
    Two common uses of the return from a function is:
    1) If there is only one value to get from the function, the return allows you to use it in equations. In x = sin(a) + cos(b), sin and cos have return values.
    2) If the success or failure status of the function operation is in question, you would often like to return the status.
    Code (Text):

    if( ! set_up_shared_memory() ){
       printf("ERROR: Shared memory not set up\n");
    }
     
     
    Last edited: Dec 30, 2015
  6. Dec 30, 2015 #5
    C code is converted into assembly language in the compilation process. There you don't really have the notion of functions quite like you have in C. It's more like just writing values to registers and memory addresses and using goto like statements to jump around in the code.

    For the return value, it's a convention that it's stored in a specific register. This is done simply so that assembler coders or C or C++ compilers agree on where the value returned from a C function should be put. This way, the calling code can look in the register to retrieve the value after calling the function. So you basically can rely on the fact that when a C or C++ function returns something, what it returns will be in a specific place.

    Registers are also used for various things by the operating system for example, and some code may write to those registers behind the scenes when you do things like print, draw, get user input etc. You may also simply pass pointers ( memory addresses ) as arguments to the function and then write values to their corresponding cells of memory. I would consider all of these things output I guess. I suppose at the fundamental level I would consider the output to be the set of changes to the state of the machine resulting from calling the function.
     
    Last edited: Dec 30, 2015
  7. Dec 30, 2015 #6

    Mark44

    Staff: Mentor

    Languages other than C and C++ distinguish between functions (that return a value) and procedures or subroutines (that perform some task). In C and C++ there are just functions, though. A function that is declared and defined as a void function does not return a value. A function that is declared and defined as int fun() or char fun() or float fun() etc. returns a single int, char, or float, respectively.

    A void function is the C/C++ equivalent of a subroutine (Fortran designation) or procedure (Pascal designation).
    Yes, absolutely.

    Here's an example definition:
    Code (Text):
    int sum(int a, int b)
    {
       return a + b;
    }
    The function above takes the int values passed as parameters, adds them, and then returns that sum, as an int. It would be used like so:
    Code (C):

    .
    .
    result = sum(4, 6);
    .
    .
     
    Last edited: Jan 5, 2016
  8. Dec 30, 2015 #7

    jtbell

    User Avatar

    Staff: Mentor

    I think at the end of this sentence you meant to write something like "(that perform an operation)".
     
  9. Dec 30, 2015 #8

    jtbell

    User Avatar

    Staff: Mentor

    I'll add to Mark's example that you can also do it as follows, using a void function that has a third argument for passing the result back to the calling function via a pointer:
    Code (C):

    void add (int a, int b, int *c)
    {
      *c = a + b;
    }
     
    You would call it like this:
    Code (C):

    .
    .
    add (4, 6, *result);
    .
    .
     
    You can call Mark's function twice in the same statement if you like:
    Code (C):

    result = sum(4, 6) + sum(3, 5);
     
    but you can't do this with a void function, so you have to use a more cumbersome process to get the same result:
    Code (C):

    add (4, 6, *term1);
    add (3, 5, *term2);
    result = term1 + term2;
     
    In C++ most programmers would use a reference instead of a pointer argument:
    Code (C):

    void add (int a, int b, int &c)
    {
      c = a + b;
    }
     
    Code (C):

    .
    .
    add (4, 6, result);
    .
    .
     
    (C doesn't have references.)
     
    Last edited: Dec 30, 2015
  10. Jan 4, 2016 #9
    Hello,
    After reading your useful replies and some other resources, I believe I understand that the return statement works this way:
    A certain function A (it could be the main function or any other function) "calls" another function B. When function B is called and passed certain parameters to work with, the code inside the curly brackets of function B is executed. Function B can manipulate the passed parameters, do calculations with them, etc. Function B can take the result from one of its executed instructions/operations and return it (pass it) back to the calling function to be used by it, if necessary. Some functions do no return any value to the calling function. In that case we can simply write return or write nothing. Those functions execute their code, can produce some outputs which do not get necessarily passed back to the calling function to be used by other functions nested inside the calling function....

    For example, let me write the C program example below:

    #include <stdio.h>
    long int multiply( int var1, int var2) /* this line represents prototyping the function
    main ()
    {
    int a, b;
    long int answer;
    printf("What is the first number to multiply?");
    scanf(%d, &a);
    printf("What is the second number to multiply?");
    scanf(%d, &b);

    answer=multiply(a,b)
    printf("the product equals %ld.", answer);
    return 0;
    }
    **************************
    long int multiply(int var1, int var2)
    {
    int locAnswer;
    locAnswer= var1 * var2;
    return (locAnswer)
    }

    In the simple code above, the function multiply() is called by the main() function. The function multiply() is passed the parameters a and b and produces the output variable answer used inside the main() function. For the output variable answer to be used by main(), multiply() must first return it to the main(). The expression given to the return statement in multiply() is the local variable locAnswer whose name can be different from the output variable name, answer in this case, used in the main() function....

    thanks,
    fog37
     
  11. Jan 5, 2016 #10
    That's not how I would teach it. It does return a value, it's of type void. Void is a type just like int, float, string... you can even cast to it.

    Code (Text):
    (void)0;
    Is commonly used to represent a no-operation, it takes the value 0 and casts it as void.
     
  12. Jan 5, 2016 #11

    Mark44

    Staff: Mentor

    I disagree. A void function cannot return a value. My compiler (VS 2013) flags the following as an error:
    Code (C):
    void nop()
    {
       int retvalue = 7;
       return retvalue;
    }
     
    Of course, if I change the last line above to return (void)retvalue; the compiler accepts this change, but why would I want to do this? As far as I can tell, the compiler optimizes out the revised return statement. In any case, the code that is generated does not alter the value in the EAX register, the register typically used in x86 code to hold return values.

    A few quotes from my copy of K & R, 2nd Ed.
    Bold emphasis added
    P. 30
    P. 196
    P. 199
    I've never seen any code like the above, which doesn't mean that it hasn't been used somewhere, but I have seen this quite often:
    Code (C):
    ptr = (void *)0;
     
  13. Jan 5, 2016 #12

    jim mcnamara

    User Avatar

    Staff: Mentor

    From N1570 C11 standards paragraph 6.2.5 page 41:
    19 The void type comprises an empty set of values; it is an incomplete object type that cannot be completed.

    6.3.2.1 Lvalues, arrays, and function designators
    1 An lvalue is an expression (with an object type other than void) that potentially designates an object;

    6.3.2.2 void
    1 The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression. If an expression of any other type is evaluated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)

    Section 6.3.2.2 refers to what Mark44 is discussing. Not the void pointer. The side effects comment explains what happens to void functions and expressions. They act like subroutines in other languages do, modifying variables that are in scope for the function, for instance.
     
  14. Jan 5, 2016 #13
    That's simply because it's returning the wrong type, once you cast it no void you said it worked fine.

    It's commonly used when you want different behavior depending on compilation options, here is an example:

    Code (Text):
    #ifdef USE_LESS_MEMORY
         #define process_cstring(cstr) cstr = realloc(cstr, strlen(cstr) * sizeof(char))
    #else
         #define process_cstring(cstr) (void)0
    #endif
    Most compilers will optimize an empty function away (some even support the inline keyword,) but strict C standard compilers won't so a no-op is used instead. I use it mostly on code that needs to work on embedded hardware with weird compilers. I don't think this process is used much anymore in normal coding, just special cases, but it's very common in legacy code.
     
  15. Jan 5, 2016 #14

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    This is not doing what you think it is doing. It does very similar to the use of printf by pedantically correct programmers. printf returns a value, but hardly anyone uses it. To be pedantically correct, you should tell the compiler you are ignoring that return value:
    Code (Text):
    (void)printf("%s %s\n", "hello", "world");
    Now we can see what your code is doing. Reading from right to left, the semicolon terminates the statement, the zero is an expression (but then again, so is a call to printf), and void tells the compiler to not complain that that zero is being dropped onto the bit floor. Any decent compiler will optimize that away.
     
  16. Jan 5, 2016 #15

    Mark44

    Staff: Mentor

    Yes. I changed my post accordingly.
     
  17. Jan 6, 2016 #16

    In mathematics, a function is something that pairs an input with an output. Given the input is the same, the output will always be the same.

    In C, a "function" is a call of a routine that may or may not return a value and may return a different value given the same input.

    As a programmer I tried to use honest-to-God mathematical functions. In programming this is thought of as "a subroutine with no side effects." If it has no side effects, then its only use is to return a value. This makes the program easier to managed. If everything in your program is a function then it has only one state, so it can never be in the wrong state. This eliminates that which is possibly the biggest source of error.

    This can't be done if you are dealing with hardware that doesn't following the functional paradigm, or if you are dealing with a database.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook