Thread: How does returning values from functions work?

  1. #1
    Registered User
    Join Date
    Oct 2016
    Posts
    17

    Question How does returning values from functions work?

    Hello!

    I am learning to use functions in C++. Specifically, I have questions about using the keyword "return" inside function body. I hope someone can help me understand this.

    Program 1:
    Code:
    #include <iostream>
    
    using namespace std;
    
    int myFunc(int a, int b)
    {
        int sum;
        sum = a+b;
    }
    
    int main()
    {
        cout << myFunc(1, 3);
    
        return 0;
    }
    Program 2:
    Code:
    #include <iostream>
    
    using namespace std;
    
    int myFunc(int a, int b)
    {
        int sum;
        sum = a+b;
        return sum;
    }
    
    int main()
    {
        cout << myFunc(1, 3);
    
        return 0;
    }
    Program 3:
    Code:
    #include <iostream>
    
    using namespace std;
    
    int myFunc(int a, int b)
    {
        int sum;
        sum = a+b;
        return sum;
        return a;
        return b;
    }
    
    int main()
    {
        cout << myFunc(1, 3);
    
        return 0;
    }
    Program 4:
    Code:
    #include <iostream>
    
    using namespace std;
    
    int myFunc(int a, int b)
    {
        int sum;
        sum = a+b;
        return a;
    }
    
    int main()
    {
        cout << myFunc(1, 3);
    
        return 0;
    }
    Question 1:
    What's the difference between Program 1 and Program 2? I don't understand. Why is Program 1 returning 4 when I didn't ask it to? (Or did I?...)

    Question 2:
    How did Program 1 know to return 4 and not 1 or 3?

    Question 3:
    Why does Program 3 not return 4, 1, and 3? It can only return one number at a time? And since statement to return sum comes first, it just returns it and steps out of the function?

    Question 4:
    The return type is int because of the "int" in front of myFunc()? Is this causing the function to return a value (int) even when I don't ask it to do so (when not using the return keyword)?
    Last edited by cozySam; 10-09-2016 at 06:28 AM.

  2. #2
    Registered User
    Join Date
    Oct 2016
    Posts
    17
    I can try to answer Question 3:

    It does seem like it can only return one number at a time, and order in which they appear does make a difference.

    Porgram 5:
    Code:
    #include <iostream>
    
    using namespace std;
    
    int myFunc(int a, int b)
    {
        int sum;
        sum = a+b;
        return b;
        return a;
        return sum;
    
    }
    
    int main()
    {
        cout << myFunc(1, 3);
    
        return 0;
    }
    This program returns 3, because "return b" is at the top of other return statements.

    Now that I think about it, functions can only have one single output. But they can have one or more inputs. Is that right?

    So this function then takes two inputs, and produces one output. It produces an output as soon as I call it and give it two inputs? Regardless of if I ask it to return or not? I mean it's like auto returning at the moment I call it?

    Program 6:
    Code:
    #include <iostream>
    
    using namespace std;
    
    void myFunc(int a, int b)
    {
        int sum;
        sum = a+b;
        return sum;
    }
    
    int main()
    {
        cout << myFunc(1, 3);
    
        return 0;
    }
    When I change the int to void I get an error. Two actually, one for the return statement and one for the output stream.

    Code:
    error: return-statement with a value, in function returning 'void' [-fpermissive]
    
    error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'void')
    This seems to support my view. But I still don't know how it knows what to return without me specifying it. I mean how it knows to return 4 and not 1 or 3.
    Last edited by cozySam; 10-09-2016 at 06:37 AM.

  3. #3
    Guest
    Guest
    Question 1:
    What's the difference between Program 1 and Program 2? I don't understand. Why is Program 1 returning 4 when I didn't ask it to? (Or did I?...)
    Program 1 is in error, so it's not an alternative to Program 2, which is correct. The function returning the value 4 might be undefined behavior, which is a complex topic you needn't worry about yet. If your function doesn't have a void return type, you must always return a suitable value.

    Question 2:
    How did Program 1 know to return 4 and not 1 or 3?
    See answer above.

    Question 3:
    Why does Program 3 not return 4, 1, and 3? It can only return one number at a time? And since statement to return sum comes first, it just returns it and steps out of the function?
    Yes, the first return statement encountered will "return from the function", i.e. statements following it within the function body will not be executed. It's as simple as that. If you need to return multiple values, they could be contained in a structure, but that's a topic for later.

    Question 4:
    The return type is int because of the "int" in front of myFunc()? Is this causing the function to return a value (int) even when I don't ask it to do so (when not using the return keyword)?
    Yes, the int before it specifies what it can return. Since Program 1 is in error, the scenario you lay out shouldn't concern you, it's a mistake to not return some value from a non-void function.
    Last edited by Guest; 10-09-2016 at 07:11 AM.

  4. #4
    Guest
    Guest
    This program returns 3, because "return b" is at the top of other return statements.
    Correct.

    Now that I think about it, functions can only have one single output. But they can have one or more inputs. Is that right?
    Zero or more inputs and just one output, correct.
    Code:
    int give_me_five() // no input is fine too
    {
        return 5;
    }
    So this function then takes two inputs, and produces one output. It produces an output as soon as I call it and give it two inputs? ... [return question clear now I hope] ... I mean it's like auto returning at the moment I call it?
    Correct

  5. #5
    Registered User
    Join Date
    Oct 2016
    Posts
    17
    Thank you Adrian!

    Yes, I was told on IRC that this must be some kind of UB (unexpected behavior). I made a break point inside the function of Program 1 (at line 8 I think) and posted disassembly code. For what it's worth here is the code:

    Code:
    0x401340    push   %ebp
    0x401341    mov    %esp,%ebp
    0x401343    sub    $0x10,%esp
    0x401346    mov    0x8(%ebp),%edx
    0x401349    mov    0xc(%ebp),%eax
    0x40134c    add    %edx,%eax
    0x40134e    mov    %eax,-0x4(%ebp)
    0x401351    leave
    0x401352    ret
    I usee CodeBlocks 16.01 on Windows, with GCC (MinGW) compiler.

    I can even get the number 1 printed on screen without writing anything inside function body. This must be a problem with the compiler as well.

  6. #6
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by cozySam View Post
    I can even get the number 1 printed on screen without writing anything inside function body. This must be a problem with the compiler as well.
    Turn on warnings in your compiler or IDE, and it will warn you about several things, such as failing to return a value from a function when you should have. You always have the opiton to ignore the warning and run the code anyway, but the result will be unpredictable.

  7. #7
    Registered User
    Join Date
    Oct 2016
    Posts
    17
    Just one last example!

    Program 7:
    Code:
    #include <iostream>
    
    using namespace std;
    
    char myFunc()
    {
        char* x = "Hello!";
        cout << x << endl;
    }
    
    int main()
    {
    
        myFunc();
    
        return 0;
    }
    Program 8:
    Code:
    #include <iostream>
    
    using namespace std;
    
    void myFunc()
    {
        char* x = "Hello!";
        cout << x << endl;
    }
    
    int main()
    {
    
        myFunc();
    
        return 0;
    }
    If I understand this correctly, Program 7 is wrong, and Program 8 is correct. Unless I plan on doing something with the returned value inside the main, the return type of myFunc() should be void?

  8. #8
    Registered User
    Join Date
    Oct 2016
    Posts
    17
    Quote Originally Posted by c99tutorial View Post
    Turn on warnings in your compiler or IDE, and it will warn you about several things, such as failing to return a value from a function when you should have. You always have the opiton to ignore the warning and run the code anyway, but the result will be unpredictable.
    I think it's already set, I do get the warnings.

    Code:
    warning: variable 'sum' set but not used [-Wunused-but-set-variable]
    warning: no return statement in function returning non-void [-Wreturn-type]
    But I only see this after running the program. Presumably because I use the "build and run" option in CodeBlocks.

    So unless I can tell CB to stop me from running the program if there are any warnings, I should be using the option to only build the program? Then check the build messages manually, then decide for myself if I want to run it?

  9. #9
    Guest
    Guest
    Quote Originally Posted by cozySam View Post
    Unless I plan on doing something with the returned value inside the main, the return type of myFunc() should be void?
    You got it. By the way: in C++, main is the one function that returns implicitly, so you don't need the return 0; at the end – that's taken care of.

  10. #10
    Registered User
    Join Date
    Oct 2016
    Posts
    17
    Quote Originally Posted by Guest View Post
    You got it. By the way: in C++, main is the one function that returns implicitly, so you don't need the return 0; at the end – that's taken care of.
    Yeah, I heard Bucky Roberts mention that in one of his videos. That's the new way since C++ 11 I think. I remembered that, so I was thinking if not my situation with return statement had anything to do with that. Now I know for sure, it only relates to the main(). Anyway, thanks for helping me!
    Last edited by cozySam; 10-09-2016 at 09:58 AM.

  11. #11
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by cozySam View Post
    So unless I can tell CB to stop me from running the program if there are any warnings, I should be using the option to only build the program? Then check the build messages manually, then decide for myself if I want to run it?
    You certainly could. The gear button on your toolbar in Codeblocks will build only and then you could check the logs yourself.

    There are options you could use to force yourself to write warning-free programs.

    First, with your project open, go to Project -> Build options...
    This opens a dialogue box like the attached image below. With the "Compiler settings" tab and "Compiler Flags" tab highlighted, find the "Warnings".

    There you can select the checkbox for -pedantic-errors. As described, this will treat C/C++ warnings as errors.

    In addition to this, first highlight the "Other compiler options" tab and then type -Wfatal-errors. This will tell the compiler to stop compiling for the first error it sees, so you can tackle one problem at a time.

    I actually recommend you do this when starting out. Since warnings do not stop the IDE from continuing the build phase, there is a tendency to believe they aren't as severe or can be ignored. Warnings are always a sign of a problem, though. No matter what you actually do, you should pay attention to them.

    Lastly, if you want to look up elseweb for more information on the options, I recommend reading this page.

    HTH
    Attached Images Attached Images How does returning values from functions work?-cb_options_diag-jpg 

  12. #12
    Registered User
    Join Date
    Oct 2016
    Posts
    17
    Quote Originally Posted by whiteflags View Post
    You certainly could. The gear button on your toolbar in Codeblocks will build only and then you could check the logs yourself.

    There are options you could use to force yourself to write warning-free programs.

    First, with your project open, go to Project -> Build options...
    This opens a dialogue box like the attached image below. With the "Compiler settings" tab and "Compiler Flags" tab highlighted, find the "Warnings".

    There you can select the checkbox for -pedantic-errors. As described, this will treat C/C++ warnings as errors.

    In addition to this, first highlight the "Other compiler options" tab and then type -Wfatal-errors. This will tell the compiler to stop compiling for the first error it sees, so you can tackle one problem at a time.

    I actually recommend you do this when starting out. Since warnings do not stop the IDE from continuing the build phase, there is a tendency to believe they aren't as severe or can be ignored. Warnings are always a sign of a problem, though. No matter what you actually do, you should pay attention to them.

    Lastly, if you want to look up elseweb for more information on the options, I recommend reading this page.

    HTH
    Thanks whiteflgs! I have done that now.

  13. #13
    Nasal Demon Xupicor's Avatar
    Join Date
    Sep 2010
    Location
    Poland
    Posts
    179
    I heard Bucky Roberts mention
    I'm not necessarily saying that what Bucky said in this or that instance is wrong, but... I would steer clear of his "tutorials". I'm not however denying that you can actually learn stuff in spite of them.

    UB (unexpected behavior)
    UB is undefined behavior. It's a specific term straight from ISO standards, and it's highly technical definition is: "Anything might happen, including a demon flying out of your nose and dancing macarena on your table." Don't believe the rumors though. We don't dance.

    There's also that other definition that doesn't mention any demons and is - for some reason - preferred by the C++ standard committee. Here's a quote from N3797, C++14 working draft:
    1.3.24 [defns.undefined]undefined behavior
    behavior for which this International Standard imposes no requirements
    [ Note: Undefined behavior may be expected when this International Standard omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. — end note ]
    1.3.25 [defns.unspecified]
    unspecified behavior
    behavior, for a well-formed program construct and correct data, that depends on the implementation
    [ Note: The implementation is not required to document which behavior occurs. The range of possible behaviors is usually delineated by this International Standard. — end note ]

    It's noteworthy to mention that some functions never return, by design. Think exit(), abort(), or... perpetually running function. You can even give them the special attribute [[noreturn]], like so:
    Code:
    [[ noreturn ]] void f() {
        throw "error"; // OK
    }
    (Notice that exiting a function by means of throwing an exception is not considered "returning".)
    If such a function (with [[ noreturn ]]) actually returns - macarena demons, you know the drill.
    The attribute here is optional - you can have a function that never returns without it, and if at some point it actually returns - it's all well defined. It's just something that if you're learning C++ you might have never seen before - and might not see for quite some time to follow. I wouldn't worry about it none, but it won't hurt to know stuff like that is there.

    It's actually not an error to have a function that never returns, even if it has a return type other than void. (Here's an exercise for ya! Think of an example of a function that never returns, but needs to have a return type other than void. I can think of one example. ) However:
    6.6.3 The return statement [stmt.return]
    2 [...] Flowing off the end of a constructor, a destructor, or a function with a cv void return type is equivalent to a return with no operand. Otherwise, flowing off the end of a function other than main (3.6.1) results in undefined behavior.
    So you see, your first code sample - it's definitely UB.

    As for inputs and outputs - technically, you have zero or more inputs and zero (when the return type is void) or one output . If it sounds so limiting when it comes to outputs that it's hard to believe it's true - well, that's because it's only technically true. You can only return one value from a function, with the caveat that that "value" can be a kind of a wrapper that actually holds more values, like an object of a class/structure. It's like a smartass with a large coat hiding his friends under it to pay less for the cinema ticket. He's "totes" a single value, dude. ; )

    There's also another way to have more outputs - you can pass pointers into a function and access values that are "outside" by dereferencing them, or use references to do almost the same thing, turning some of your "inputs" into effective "outputs".

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    >>char* x = "Hello!";
    If your book or tutorial is telling you this is OK, then you need to drop those books/tutorials and get a real book. First and foremost, you shouldn't be using C-style strings. You can probably google to find tons of good answers as to why not, so I'm going to avoid saying why.
    But the reason I'm calling this out specifically is that the standard has deprecated conversion of const char* -> char* for string literals since... forever. Fast-forward a few years from now, that's not going to compile any longer. The standards committee has decided that this is illegal and so beginning with C++17, that's not going to compile.

    Quote Originally Posted by Xupicor View Post
    ...There's also another way to have more outputs - you can pass pointers into a function and access values that are "outside" by dereferencing them...
    Please! No pointers! Are we discussing C or C++ here?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Nasal Demon Xupicor's Avatar
    Join Date
    Sep 2010
    Location
    Poland
    Posts
    179
    I'm just mentioning ways to do so, pointers are certainly one of them. The important point here is that you can use "inputs" as "outputs". But sure, a reference is almost always the better choice, when it can be used.
    Still, you can't escape learning pointers when learning C++. Even in 2016.

    As to char* s = "string literal" that implicit conversion was deprecated in C++98, and since C++11 there's no conversion anymore in the language. GCC in C++11 (and C++17...) mode spits out "just a warning", as does Clang in default mode:
    Code:
    char.cpp:2:15: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]     char* s = "string";
                   ^
    but it is straight invalid C++ as no conversion is there to be performed (one has to explicitly cast const away) as far as the language is concerned.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. write() and read() int values from socket returning wrong values.
    By Premjith P S in forum Linux Programming
    Replies: 8
    Last Post: 11-29-2012, 02:59 PM
  2. Returning values from functions
    By JayCee++ in forum C++ Programming
    Replies: 4
    Last Post: 10-12-2011, 11:38 AM
  3. Returning values from functions
    By g001 in forum C++ Programming
    Replies: 3
    Last Post: 10-01-2007, 03:42 AM
  4. returning multiple values from functions?
    By jamesn56 in forum C++ Programming
    Replies: 5
    Last Post: 08-23-2005, 01:10 PM
  5. Functions and Returning Values
    By jrahhali in forum C++ Programming
    Replies: 5
    Last Post: 08-22-2004, 12:13 PM

Tags for this Thread