2

According to a book I read you can pass variables from one function to another by passing by value/address. When you pass by address it will no longer preserve the variable if it is changed in a function and returned back to the original function (ex: main()). The very next chapter, the book reviews "returning values". In this chapter it explains the use of return(variable); but doesn't explain a clear purpose. Is return(variable); used when multiple variables are passed to a certain function to return only one? Or are there other uses? In other words, what's the difference between return; and return(variable);?

Passing by address, exact book example without return(num);:

#include <stdio.h>
main()
{
    int i;
    i = 4
    printf("Before: %d.\n", i);
    half(&i);
    printf("After: &d.\n", i);
    return (0);
}

half (int *i)
{
    *i = *i / 2;
    printf("During: %d.\n", *i);
    return;
}

Returning Values, exact book example with return(num);:

#include <stdio.h>
float gradeAve(float test1, float test2, float test3);

main()
{
    float grade1, grade2, grade3;
    float average;

    printf("What was the grade on the first test? ");
    scanf(" %f", &grade1);

    printf("What was the grade on the second test? ");
    scanf(" %f", &grade2);

    printf("What was the grade on the third test? ");
    scanf(" %f", &grade3);

    average = gradeAve(grade1, grade2, grade3);
    printf("\nWith those three test scores, the average is %.2f", average);

    return 0;
}

float gradeAve(float test1, float test2, float test3)
{
    float localAverage;
    localAverage = (test1+test2+test3)/3;
    return (localAverage); 
}

How can both of these return values to original function with or without return(num);?

8
  • 2
    Your question is unclear, perhaps because you're confused. Please post a minimal but complete example and ask a question based on that. May 14, 2016 at 18:02
  • Edited for clarity
    – Samuel F
    May 14, 2016 at 18:16
  • Post-edit, the literal answer is "return; without a variable name just returns nothing" which seems so obvious it's still unclear to me what you need help with (again, probably due to the confusion). Are you saying you'd expect a function to return one of its arguments even without you writing a return statement? Or are you wondering what the point of a return; statement is when it's not returning a value? Or are you trying to ask something about returning one of the parameters that was passed into the function?
    – Ixrec
    May 14, 2016 at 18:17
  • Functions are similar to that in math. They take arguments and return a value. If you want to return more than one value you have several options: you can return a struct, which is combination of values, or, you can modify some memory that both the caller and callee have access to. One way to provide a location or memory that both caller and callee have access to is to supply an address to the call. You can't use return; in a function, that would be a compile-time error. A procedure has void return and cannot return a value (also would be compile-time error).
    – Erik Eidt
    May 14, 2016 at 18:20
  • 1
    FYI, return value; doesn't need ()'s. We can add extra ()'s to any expression if desired, such as 1+2 can be written as ((1)+(2)), so some do that as return (value); even though it is does nothing different from return value;.
    – Erik Eidt
    May 14, 2016 at 18:29

3 Answers 3

1

How can both of these return values to original function

They don't; your book is badly-worded.

  • In the second case:

    average = gradeAve(grade1, grade2, grade3);
    

    gradeAve returns - literally with a return statement - its result. Here the function parameters (grade1..3) are just inputs, and the whole call looks like a mathematical expression.

  • In the first case:

    half(&i);
    

    nothing is returned. The caller's local variable, i, is mutated by the function half, so that afterwards its value is different. This is called an out-parameter, meaning one of the function's parameters is used for output from the function, instead of input to the function as is usually the case.

    This style usually isn't preferred because it is less clear: there's nothing to tell me when reading the calling code that i is changed by the call until I also read the implementation of half.

    The main exception is when the out-parameter is large in size (so would be expensive to copy by value in a return statement), or is an object with some kind of identity rather than a simple value.

One source of confusion (apart from the poor wording in the book) is that return does two things:

  1. passing a result from a function back to the caller
  2. passing control from a function back to the caller

So for example:

void mutate(int *i) {
  if (*i < 0) {
    return; /* just quit the function early */
  }
  (*i) = mutate_nonnegative(*i);
  /* return is implied here */
}

uses meaning #2 only, while

int mutate_nonnegative(int i) {
  if (i % 2) {
    return 3 * i; /* triple odd numbers */
  } else {
    return 2 * i; /* double even numbers */
  }
}

uses both #1 and #2 (it quits the function and returns to the caller at different points, passing the caller a different value at each).

6
  • Fantastic, but. Why/When "return value;"?
    – Samuel F
    May 18, 2016 at 21:10
  • The noun phrase "return value" means literally the value passed back to the caller with a return statement. The verb phrase "to return a value" might metaphorically include cases where optimisation replaced a return statement with an out parameter.
    – Useless
    May 18, 2016 at 21:38
  • What's the point of returning a value when the value will change regardless when the function ends and the caller function resumes?
    – Samuel F
    May 19, 2016 at 1:01
  • I think you need to look at some actual code and think about what it does, and why. I've told you what the difference is between the two things, but don't think this is a good format for exploring the motivation for both existing.
    – Useless
    May 19, 2016 at 9:24
  • Thank you. One last question, in book example 2. How can the program assume that when "test1, test2, test3" is used its values are the same as "grade1, grade2, grade3"?
    – Samuel F
    May 20, 2016 at 1:26
1

I'm still very confused by this question but might as well try...

In your half function, the return; statement doesn't do anything useful. If you left it out the function would behave exactly the same way. Similarly, the parentheses in return (localAverage); also do nothing and are better left out.

Normally return; is only useful when you want to return from the function "early", without waiting to hit the closing curly brace. As a trivial example:

saferHalf (int *i)
{
    if(i == NULL) {
        return;
    }
    *i = *i / 2;
    printf("During: %d.\n", *i);
}

How can both of these return values to original function with or without return(num);?

In general, there are only two ways to "return a value" from a function. First, you actually return a value, which means using return value;. Second, you pass the function an "output parameter", i.e. a pointer to some variable that the function is supposed to modify using that pointer.


I'm not sure if you were confused on this point, but passing or returning by value or address has nothing to do with return; vs return value; or anything like that. Strictly speaking, C always passes by value and returns by value. The values you pass and return can be pointers, and you can call that "passing/returning by pointer/address" if you want to, but the semantics of passing and returning are always the same way whether or not the values being passed and returned happen to be pointers.

2
  • I guess I need to get down to basics. When I "return values" or "pass by address/value" what am I actually doing?
    – Samuel F
    May 15, 2016 at 15:05
  • In terms of language semantics, the value of a function call expression such as half(2) is determined by what value the half function returns, so the return value; statement is saying "whoever just called me, this is the value you're getting back". If you're asking what happens at the level of assembly language and machine code, your compiler and optimizer can do all sorts of things to make it as efficient as possible, but conceptually it'll always write the value to some CPU register or RAM location so that whoever called that function can get at it.
    – Ixrec
    May 15, 2016 at 15:11
0

You can use either method to return values back to the caller. However in general I'd use the following.

Save the "return value" for the logical outcome of an operation. Eg, this worked, there was an error, etc. If your method want to return some computed value, send the container for that data in the request and collect the result from there.

However, this rule is made to be broken, so if you'd just want to return the outcome of a simple addition use the main return value, rather than having to pass the answer contained in with the original parameters.

1
  • "Save the "return value" for the logical outcome of an operation.": One may say that everything you do during a function / procedure call contributes to its "logical outcome". If your function needs to return more than one value, you can always use a tuple / object / record. Bottom line: you do not need to mutate function parameters or global variables to return something.
    – Giorgio
    May 16, 2016 at 18:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.