Functions and Return statement in C

  • Thread starter fog37
  • Start date
  • Tags
    Functions
In summary, a function can have one of four types of inputs and produce one of four types of outputs. Functions of type 1) receive inputs and produce outputs, functions of type 2) receive no inputs and produce no outputs, functions of type 3) receive inputs and produce no outputs, and functions of type 4) receive no inputs and produce outputs. Functions of type 1) and 4) always include the instruction return, but the return statement is not needed for functions of type 2) and 3). Functions of type 2) may include a return statement, but the return keyword is followed by an expression, and functions of type 3) do not include a return statement. If a function needs to return more than one output, the function can return
  • #1
fog37
1,568
108
Hello,
In C (or C++), a function is a body of instructions. Functions can be classified as functions that

1) receive inputs and produce outputs
2) receive no inputs and produce no outputs
3) receive inputs and produce no outputs
4) receive no inputs and produce outputs

For case 1) and 4), the function body must alwaysinclude the instruction return, correct? The argument of return is the output of the function. What if the function needed to produce more than one output? Can the return instruction handle more than just one output?

Thanks
 
Technology news on Phys.org
  • #2
fog37 said:
Hello,
In C (or C++), a function is a body of instructions. Functions can be classified as functions that

1) receive inputs and produce outputs
2) receive no inputs and produce no outputs
3) receive inputs and produce no outputs
4) receive no inputs and produce outputs

For case 1) and 4), the function body must alwaysinclude the instruction return, correct? The argument of return is the output of the function. What if the function needed to produce more than one output? Can the return instruction handle more than just one output?

Thanks
You can return a class that encompasses all of the data that you wish to return.
 
  • Like
Likes QuantumQuest and jedishrfu
  • #3
You can always return output through arguments.
 
  • Like
Likes rbelli1 and jedishrfu
  • #4
Yes, 1 and 4 require return statements. The compiler determines this from the function signature. So if you say you're returning an integer value then the compiler expects you to have a return statement to return that type of value.

In C you can't return more than one piece of data so when a function needs to return more, you would define a struct with the information to be returned, fill it in and then return that struct reference.

Here's a simple example:

https://cboard.cprogramming.com/c-programming/149372-returning-struct-function.html

As @DrClaude says you can return values through some arguments if they are defined as pointers or array references. I tend not to do that because its more difficult to implement well without potential side effects.

Here's a more detailed discussion on it:

http://www.yukselgunal.org/c/pointers_in_func_args.pdf
 
  • Like
Likes QuantumQuest, Borg and jim mcnamara
  • #5
fog37 said:
In C (or C++), a function is a body of instructions. Functions can be classified as functions that

1) receive inputs and produce outputs
2) receive no inputs and produce no outputs
3) receive inputs and produce no outputs
4) receive no inputs and produce outputs
Not mentioned already is that functions of type 2 or 3 are called void functions. Their prototypes (or declarations) would look like this:
C:
void func2(void); // Type 2 -- no parameters
void func3(...);  // Type 3 -- nonempty parameter list
These functions can have a return statement, but it would be an error if the return keyword were followed by an expression, as in return some_value;
 
  • Like
Likes jedishrfu
  • #6
fog37 said:
What if the function needed to produce more than one output? Can the return instruction handle more than just one output?
as far as I know, not in general, at least not in the same way python can...
In general one way I've seen people using C++ to return more than 1 outputs is by using the "pass-by-reference" in the functions' arguments... that way you can change the value of a variable within the function by accessing the variable's address.
This effectively acts as returning multiple outputs...since the function will have (or may not have) a single return , but in its body it will be able to update/change additional variables (so producing new outputs out of them). The bad thing is that your initial variables are going to be lost (?) but this may not be a problem if you create them just for that purpose...

for example, ROOT TH1 class gives the ability to calculate the integral and its error by the TH1::IntegralAndError() method (https://root.cern.ch/doc/master/classTH1.html#ace3e72fc1df4a16db0d3c86230b39502).
This method can 3 arguments: the first bin, the last bin (for your integration) and a variable that keeps the error. So you could get two values of it: the integral and its error...
Code:
Double_t err(0.0);
Double_t Integral;
//calculates the integral of the histogramTH1 (a TH1 histogram object) from bin=0 to bin=5.
Integral= histogramTH1.IntegralAndError( 0, 5 , err );
//err is passed by reference here
// so chances are it's going to be changed within this method/function.
// err is not going to be 0.0 now if there's error to calculate...
std::cout << "Integral  = " << Integral << " +/- " << err <<std::endl;

In general when you see some argument passed as reference in C++, it means that either the variable you give is going to be modified or you want to avoid copying it (that's what pass-by-value does). The second is often the case when you have large objects, where copying them costs extra time. If I sent you in a city, and told you "can you check whether the street numbers add up to 1000", it would be better for you to go and have a look in the city itself rather than building an identical city and summing its street numbers. On top of that, in this case, you should pass your object with const (to ensure and let others know, you don't intend to change it).
 
Last edited:
  • #7
ChrisVer said:
In general one way I've seen people using C++ to return more than 1 outputs is by using the "pass-by-reference" in the functions' arguments
But technically, the function isn't "returning" multiple values when it alters arguments that have been passed by reference. A C or C++ function can still return only one thing (which might be a structure with multiple members).
 
  • #8
well, yes, but effectively it's a multiple return, since you have a function that returns several outputs (without using the return statement).
The rest is all about semantics and about what one means by "return"... Is it just what's written after the return statement or the actual manipulated variables? (afterall that's the main reason to use functions).
 
  • #9
ChrisVer said:
well, yes, but effectively it's a multiple return, since you have a function that returns several outputs (without using the return statement).
The rest is all about semantics and about what one means by "return"... Is it just what's written after the return statement or the actual manipulated variables? (afterall that's the main reason to use functions).
I think that most would call what's returned by a function the expression that comes in the function's return statement. Others might fudge a bit, and phrase things as "after the function returns, the variables x, y, and z have their values changed." Strictly speaking, in my view, anyway, the function doesn't "return" x, y, and z.
 
  • Like
Likes QuantumQuest
  • #10
ChrisVer said:
In general when you see some argument passed as reference in C++, it means that either the variable you give is going to be modified or you want to avoid copying it (that's what pass-by-value does).
You can also have a parameter that is a constant reference, as in const int& param. In this case, the programming is saying that even though param is passed by reference, the code won't change its value.
ChrisVer said:
The second is often the case when you have large objects, where copying them costs extra time.
Right, and the reason for this is that what is passed is the address of the object that is referred to. At least that's the way pass-by-reference is implemented in Visual Studio. I'd be surprised to find it implemented differently in another compiler.
What I found was that exactly the same code was emitted by the compiler for a parameter that was a reference parameter or for a parameter that was a pointer. The only difference between the two ways is the semantics of declaring the parameters in the function's parameter list, and how the function is called.
 
  • #11
In general, I am not a fan of arguments that can be changed by the calling routine. In the early days of Fortran IV, I was burned by a most mysterious bug. I was using some calcomp plot functions to draw floor plans (that's what I told my boss, but the real reason was to draw a poster sized Star Trek Enterprise which never happened).

I called a library function in which the examples all showed variables as the arguments and I used a literal 3 in one of the arguments. 2 was used to lower the plotter pen and 3 was used to raise it. The program ran but only some portion of the plot came out and there were lines everywhere.

Eventually I tracked it down to that one function which changed the 3 to some other number and because the Fortran of the time consolidated all literals in memory i.e. there was one and only one 3 value in the pool, the change effectively changed everywhere the literal 3 was used.

What a mess! In changing the 3, I was no longer able to raise the pen when I called the plot function with a 3 hence the massive mess of lines.

Fortran IV used "call by reference" for variables and for literals as arguments to a function and was probably the leading reason for why other languages started passing literals as call by value. The machine instruction set allows for it but the Fortran calling scheme used addressing registers to locate argument values which meant call by value was out.

Here's a little more context on this issue:

https://everything2.com/title/Changing+the+value+of+5+in+FORTRAN
 
  • #12
jedishrfu said:
In general, I am not a fan of arguments that can be changed by the calling routine.
Makes it hard to write something as simple as a swap() function to swap the values of two variables. Of course, you could pass in a struct that contains the two variables, and return the altered struct, but that seems like a lot of extra work to go to.

I've been writing C code for 30+ years, and C++ for not quite as long, so pointer parameters are second nature to me by now.
 
  • #13
Mark44 said:
You can also have a parameter that is a constant reference, as in const int& param. In this case, the programming is saying that even though param is passed by reference, the code won't change its value.
I agree, that's why I also said "On top of that, in this case, you should pass your object with const (to ensure and let others know, you don't intend to change it)."

Mark44 said:
What I found was that exactly the same code was emitted by the compiler for a parameter that was a reference parameter or for a parameter that was a pointer. The only difference between the two ways is the semantics of declaring the parameters in the function's parameter list, and how the function is called.
I don't think this is compiler dependent? Except for if the compiler affects how variables are treated in memory... Referencing seems like a "memory" thing to me.

jedishrfu said:
Fortran IV was call by reference for variables and for literals as arguments to a function and was probably the leading reason for why other languages started passing literals as call by value. The machine instruction set allows for it but the Fortran calling scheme used addressing registers to locate argument values which meant call by value was out.
Again, I think the const keyword is strong in this case, since it wouldn't change your value... If the program intended to change that variable, then you must have used a wrong package - or you should have hacked it...
To me it's really convenient especially for cases when values of a variable need to be updated for any sort of a reason, or for making the program even more modular than normal... eg a user prompt input could be used in a different function or method and the user input can be read anywhere afterwards because you passed them as refs.
 
  • #15
I wasn't even thinking in FORTRAN... I am happy I was done with it as a freshman in my bachelor...
 
  • #16
The value returned is the result of the function, a function does not have various results.
However, the value returned can be a pointer to a memory location, and that location can be the starting address for as much data as you like.
 

Related to Functions and Return statement in C

1. What is a function in C?

A function in C is a block of code that performs a specific task. It can be called multiple times within a program, making the code more organized and easier to maintain.

2. How do you declare a function in C?

To declare a function in C, you use the keyword "void" followed by the function name and a set of parentheses. Inside the parentheses, you can include parameters which act as variables within the function.

3. What is a return statement in C?

A return statement in C is used to send a value back to the calling function. This value can be a variable, constant, or expression. It is placed at the end of a function and is followed by the value that is to be returned.

4. How do you use a return statement in C?

To use a return statement in C, you first declare the return type of the function. This can be "void" if the function does not return any value, or it can be any other data type. Then, within the function, you use the keyword "return" followed by the value that you want to return.

5. Can a function have multiple return statements in C?

Yes, a function can have multiple return statements in C. However, only one return statement will be executed when the function is called. The other return statements will be ignored. It is important to note that a function with a return type other than "void" must have a return statement in each possible execution path to avoid errors.

Similar threads

  • Programming and Computer Science
Replies
15
Views
2K
  • Programming and Computer Science
Replies
10
Views
1K
  • Programming and Computer Science
Replies
2
Views
1K
  • Programming and Computer Science
Replies
12
Views
1K
  • Programming and Computer Science
Replies
30
Views
4K
  • Programming and Computer Science
Replies
9
Views
1K
  • Programming and Computer Science
Replies
2
Views
905
  • Programming and Computer Science
Replies
31
Views
3K
  • Programming and Computer Science
Replies
23
Views
2K
Back
Top