views:

64

answers:

5

Given the two code examples which is preferred? In the first the return variable is defined as a local variable. In the second the return variable is passed by the caller. Are you allowed to define a function and return a variable that was passed to it? I's this simply a preference of one or the other? is there a performance difference?

float compute_diam(float circumference, float pi) {

float rval;

/* Circumference = pi * diameter, so
   diameter = circumference / pi */

rval = circumference / pi;

return rval;
}

and

float compute_diam(float circumference, float pi, float rval) {

/* Circumference = pi * diameter, so
   diameter = circumference / pi */

rval = circumference / pi;

return rval;
}

Thanks

A: 

I'd prefer the first as the second doesn't make any sense. The second you're not passing in a reference or a pointer to the rval so you're just assigning to a local variable (as you are in the first, yet it's created differently) and then returning a copy of that variable to the caller. Note that you're not saving the value in the rval passed TO the function, you're saving it in the local rval created BY the function via the parameter list.

Even if the second example was passing a reference to rval, I would still prefer the first as rval is a regular type and is easily and efficiently copied. I also find:

float diameter = compute_diam(circumference, pi);

much more readable and concise than:

float diameter = 0;
compute_diam(circumference, pi, diameter);

If you were putting data into a large object/struct, then passing a reference into the function would make more sense. A compiler many times can optimize out the copy associated with a function that incurs a copy for the return value, so I would probably stay with option 1 until you find through the use of a profiler that it needs to be optimized to something like the 2nd version.

Also, you could remove pi from the argument list and make a static const float PI = 3.14xxxx; inside the function body.

RC
A: 

This let me think that you don't understand what a return value is or how arguments are given to a function.

In your second example, you will not modify the rval that you are giving at function call, but a copy of it. And you will then return the value of rval.

Your second example is then "wrong" (from a logic point of view).

What you were trying to do is

void compute_diam(float circumference, float pi, float& rval) {

/* Circumference = pi * diameter, so
diameter = circumference / pi */

rval = circumference / pi;

}

Edit: Correction, the above is only C++, in C you would do the following

void compute_diam(float circumference, float pi, float* rval) {

/* Circumference = pi * diameter, so
diameter = circumference / pi */

*rval = circumference / pi;

}

Where rval is given by reference and where the function doesn't return anything (void).

But this should be avoided in that simple case, the interface is more clear if the function return a value.

Edit: To convince you that your second example is ill formed, think about the following:

float my_result = compute_diam(2.0, 3.14, 'why and what would I put here ? my_result ? ')

Cedric H.
-1; That isn't legal C.
Clark Gaebel
sth
My bad, I was thinking this had a C++ tag ...
Cedric H.
+2  A: 

I think in these two cases the 1st one is better for following reason 1. Due to performance as you are passing variable by value it is once created where ever you declare rval, and once when you pass that rval to function with value of first rval copied to second.

instead if you want to pass variable in this manner pass it by reference as

void main()
{
float result;
compute_diam(2.1, 3.14, &result);
 } 
void compute_diam(float circumference, float pi, float* rval) {

/* Circumference = pi * diameter, so
   diameter = circumference / pi */

*rval = circumference / pi;


}

after completion of the function variable result will hold the value of diameter.

Ahsan Iqbal
In your example you are not passing `rval` by reference but a pointer to it which is different, although equally correct.
Cedric H.
Passing the pointer IS pass-by-reference. There's no such thing as a reference in C.
Clark Gaebel
My bad, I was thinking this had a C++ tag ...
Cedric H.
A: 

Sometime you may want to pass the reference of the variable and then fill it will appropriate value or return codes.

However the second definition does not make any sense.

int foo()
{
int a=6;
return a; // This is ok
}

int foo(int a)
{
a = 5;
return a; // Calling function cant access the value 5 in the parameter 
//passed, it has to hold it in another variable
}

void foo(int* a)
{
*a=5;
return; // Here you can return and still access the value 5 in the calling 
//function with the variable passed to it
}

Hence i am assuming you want to decide between first and third method and i would say its implementation specific. If you want to pass a sequence of return values(read array,structures) you can use the second.

Praveen S
Same as @Ahsan, You are not passing `a` by reference ... It is a pointer to an int...
Cedric H.
#Cedric - In C, Pass-by-reference is simulated by passing the address of a variable (a pointer) and dereferencing that address within the function to read or write the actual variable. This will be referred to as "C style pass-by-reference." - source http://stackoverflow.com/questions/2229498/passing-by-reference-in-c
Praveen S
My bad, I was thinking this had a C++ tag ...
Cedric H.
A: 

Typically, the only reasons to store the return value at an address passed as a parameter are:

  • You need to return multiple values.
  • You need to return a structure.
  • You need to use the return value of the function to return errors.
  • The function is designed to modify one of the parameters.

If you look through the standard C library, or most any API, you'll find few instances of return values stored at an address passed as a parameter.

tomlogic