This question already has answers here:
function parameter evaluation order
(5 answers)
Closed 8 years ago.
I have this problem with my functions.
in the main function I have this result(param, param) function which takes 2 functions as parameters.
result(name(), score());
However when the code executes the score() function executes first and not the name() function. why does that happen.
(Also another problem that arises from the score() function executing first and not the name() function is that I get the \n read and the name() function is skipped altogether. However I know how to fix that I just need to know why isn't the name() function executed first. ).
I found this here: http://en.cppreference.com/w/cpp/language/eval_order.
Order of evaluation of the operands of any C++ operator, including the order of evaluation of function arguments in a function-call expression, and the order of evaluation of the subexpressions within any expression is unspecified (except where noted below). The compiler will evaluate them in any order, and may choose another order when the same expression is evaluated again.
There is no concept of left-to-right or right-to-left evaluation in C++, which is not to be confused with left-to-right and right-to-left associativity of operators: the expression f1() + f2() + f3() is parsed as (f1() + f2()) + f3() due to left-to-right associativity of operator+, but the function call to f3 may be evaluated first, last, or between f1() or f2() at run time.**
But my program always executes the score() function first. And above it states that it is random so I should at least have the name() function executed first sometimes right?
Full code is here for reference.
#include <iostream>
#include <string>
using namespace std;
string name()
{
string fname;
cout << "Please type your full name: ";
getline(cin, fname);
return fname;
}
int score()
{
int points;
cout << "Please type your score: ";
cin >> points;
return points;
}
void result(string fname, int points)
{
cout << "Ok " << fname << ", your score of " << points << " is ";
if (points > 100)
{
cout << "Impossible";
}
else if (points == 100)
{
cout << "Perfect!!!";
}
else if (points >= 85 && points < 100)
{
cout << "Amazing!!";
}
else if (points >= 70 && points < 85)
{
cout << "Good!";
}
else if (points >= 50 && points < 70)
{
cout << "Ok.";
}
else if (points < 50)
{
cout << "Bad...";
}
else
{
cout << "Incorrect input";
}
}
int main()
{
result(name(), score());
return 0;
}
In this line:
result(name(), score());
the order of evaluation for the function arguments is not defined. It just so happens that this is the order of evaluation with your particular compiler (and compiler flags). If you want the functions to be executed in a particular order then you'll ned to call them in the required order first:
string s = name();
int t = score();
result(s, t);
It's not random, it's unspecified.
Which means that the compiler is free to do what it wants.
Here the compiler decided that it's best to always call score() before name(), and will not change its mind without a good reason.
Maybe another compiler would have decided something else, maybe it depends on the phase of the moon, you can't tell and you're not supposed to try to guess what's going to happen.
Unspecified means that you can't expect it to behave in any particular way, you can't rely on it.
Related
I have been learning c++ recently. When I tried to run the following lines...
#include <iostream>
short a = 0;
short b = 1;
short c, i;
void Fibonacci(){
std::cout << a;
std::cout << b;
while (a <= 100){
c = a + b;
a = b;
b = c;
std::cout << c;
}
}
int prime_number(short a){
if (a == 1){
std::cout << "It's a prime number\n";
} else{
for (i = 2; i < a; i++){
if ((a%i) == 0){
std::cout << "It's a prime number\n";
std::cout << "The given number is divisible by " << i << "\n";
return 0;
}
}
std::cout << "It's not an prime number";
}
}
int main(){
short user_input;
std::cout << "Press 1 for Fibonacci and 2 for prime number";
std::cin >> user_input;
if (user_input == 1){
Fibonacci();
}
if (user_input == 2){
std::cout << "Type the number to check whether it's prime";
std::cin >> a ;
prime_number(a);
}
}
...I get an error saying:
In function ‘int prime_number(short int)’:
Function.cpp:37:1: warning: control reaches end of non-void function [-Wreturn-type]
37 | }
I searched various platforms for the answers, but I couldn't understand what really happens here. It's an error because the compiler cannot find whether the function has an end or not. Can someone help me understand the error and solve it?
Warnings aren't errors. When you compile a program and only get warnings (ie. no errors) then this means your program has successfully compiled (an executable has been made). When you get errors, this means that compilation was aborted (so no executable output - if you already had one, it won't have been updated).
It's warning you that when the integer input is 1 that you aren't specifying a return — which is invalid. Also, if it's not 1, then the the else statement still doesn't guarantee a returned value:
for (i = 2; i < a; i++){
if ((a%i) == 0){
std::cout << "it's a prime number\n";
std::cout << "The given number is divisible by " << i << "\n";
return 0;
}
}
The compiler can't know that return 0 will always be executed here - and even if it could, the compiler isn't designed to always understand the logic of your code. Even knowing your logic, return 0 will only be executed if a is greater than 2 and non-prime.
You could fix this by putting return statements in both of your if statements, or even at the end of your function. But notice that you never use the return value? This implies that your prime_number() function should be void prime_number(), then you won't need return values at all, and can just use break; in your loop - or return; if you prefer (here's an example of how to resolve this particular issue - there's still other bugs though, discussed below).
This is probably confusing to a beginner: Why doesn't it warn you when the function int main() contains no return value? This is because main is special: If no return value is given, it implies return 0.
Another thing that may confuse you here is if you ever compile with the flag -Werror. If you do, then the original code will give you an error, because the Werror flag turns all warnings into errors (to force programmers to pay attention to the warnings).
The logic of your code isn't right - it's actually the opposite: 1 is defined as not a prime number (this is because of the value we get from unique prime decomposition, so mathematicians chose to exclude 1 as prime). Also, ((a%i) == 0) means that when a is divided by i that it has 0 remainder, ie. i divides a, so a is not prime.
Finally, avoid using global variables. Keep all your variables local so that the logic of your code is simpler (easier to read / less bug-prone).
Here's an example of how you could rewrite your code that resolves all the above issues.
As Elliott in the comments has said the warning you are getting is not going to affect your program at all. It's recommend that you return something since you function has a return type of integer.
Below is a easy fix to get rid of the warning. :)
Old Code:
if (a == 1)
{
std::cout << "Its a prime number\n";
}
New Code without the Warning:
if (a == 1)
{
std::cout << "Its a prime number\n";
return 0;
}
I'm trying to understand what's going on under the hood of c conversions, and different types promotions and comparing stuff and all of this.
union myUnion{
int intVal;
float floatVal;};
if (m.floatVal == m.intVal)
{
cout << "BINGO!";
}
if (*ptrInt == *ptrInt2)
{
cout << "BINGO!" << endl << *ptrInt << endl << *ptrInt2;
}
The first if statement is evaluated to false and the second if statement to true.
How c compiler interprets this values m.floatVal, m.intVal. I'm mean what's going on down there, into assembly, because that's going to be run on the CPU.
Moreover m.floatVal, m.intVal gets evaluated different values depending on which variable I initialised first.
m.floatVal = 3; first gets something
m.intVal = 3; first gets something else.
In the end there is the same value there!?!?!?!?!?!?
Second example:
char minstogo = 0x98;
if (minstogo <= 7) {
cout << "BEAST!";
} beast is printed
char minstogo = 0x98;
if ((unsigned char)minstogo <= 7) {
cout << "BEAST!";
} nothing is printed
char minstogo = 0x98;
if (minstogo <= (unsigned char)7) {
cout << "BEAST!";
} beast is printed
How the compiler interprets this mess and what is going on down the assembly?
Third example:
How is a float converted to an int? Who the bits are all remapped?
Thank you so much guys! Thank you.
First example:
union myUnion{
int intVal;
float floatVal;};
if (m.floatVal == m.intVal)
{
cout << "BINGO!";
}
This is undefined behaviour in c++. Having written to intVal, reading floatVal is undefined behaviour. Having written to floatVal, reading intVal is undefined behaviour.
I am making a program that the user inputs integers and outputs them in reverse. It is a recursive function. The Problem now is that it outputs an infinite of 0's. Please tell me where is the error in my code. and I need some pointers. Please help.
#include <iostream>
using namespace std;
void printreverse(int);
int main()
{
int x;
cout << "Enter numbers: ";
cin >> x;
printreverse(x);
return 0;
}
void printreverse(int x)
{
if(x<10)
cout << x;
else
cout << x%10;
printreverse(x/10);
}
You have wrong identing in printreverse. It should be like this:
void printreverse(int x)
{
if(x<10)
cout << x;
else
cout << x%10;
printreverse(x/10);
}
First it prints x or x%10, then it recurses regardless of what x is. If you wanted more than one statement done in a consequent or alternative you need to use a block. Blocks are denoted with {} in C-decendants. They are so usual that some people actually think conditionals and control flow syntax need to have them. Anyway if the identing was the intended behaviour you should write it like:
void printreverse(int x)
{
if(x<10) {
cout << x;
} else {
cout << x%10;
printreverse(x/10);
}
}
Whenever I use braces on one term in an if I add them for every one even when it's not really needed. Some coding standards, like PSR2, require blocks always to remove the chance of ever getting bugs like this.
C++ is not Python. You need to surround your else block by braces, like so
else
{ // need brace here
cout << x%10;
printreverse(x/10);
} // and here
otherwise only the first statement after the else is being executed (and the final printreverse(x/10) will always be executed, even for 0, so you end up overflowing the stack).
I recommend you to always put braces, even for a single statement in an if/else, precisely for reasons similar to the one you just bumped into.
This question already has an answer here:
The output of cout << 1 && 0;
(1 answer)
Closed 7 months ago.
Consider:
int i = 56, j = 0;
int n = i&&j;
cout << i&&j;
cout << endl << n;
whose output would be:
56
0
I imagine it's either because of operator precedence or logical short circuit, but I can't seem to figure out which, or the reason.
The expression cout << i&&j is equivalent to (cout << i) && j. Both operands are evaluated and converted to bool. The statement as a whole has no effect, but the evaluation of the subexpression cout << i has the usual side effects, of course, namely writing something to the standard output.
The && operator is indeed short-circuited and j is only evaluated if cout << i evaluates as true. This condition is equivalent to cout.good(), which is usually the case (unless you somehow managed to close your standard output).
As you expected, the << operator comes takes precedence over &&.
Thus, cout << i&&j first outputs i, then compares the returned stream to j (both are true, so the returned value is true, but this value is discarded).
See here for the full list of operator precedence.
During work over a simple project I have found situation that I don't fully understand. Consider following code:
#include <iostream>
using namespace std;
bool test(int k)
{
cout << "start " << k << endl;
bool result; // it is important that result's value is opposite to initial value of recheck in main()
result = false;
return result;
}
int main()
{
bool recheck;
recheck = true;
for (int i = 2; i > -1; i--)
{
recheck = (recheck || test(i)); // (1)
cout << i << " ???" <<endl;
}
cout << "----------------------------" << endl;
cout << endl;
recheck = true;
for (int i = 2; i > -1; i--)
{
recheck = (test(i) || recheck); //different order that in (1)
cout << i << "???" <<endl;
}
return 0;
}
It returns completely different results from for loops:
2 ???
1 ???
0 ???
----------------------------
start 2
2???
start 1
1???
start 0
0???
It seems that it first one test(int k) is not even invoked. I suspect it has something to do with || operator. Could anybody explain such a behavior?
The built-in || short-circuits: if the left operand is true, the right operand is not evaluated (it doesn't matter what the value of the right operand is, because the value of the || expression is guaranteed to be true in this case).
For completeness, but not particularly relevant to the question: In c++, the || operator is overloadable, just as many other operators are. If an overload is used, short circuiting does not take place.
The boolean operators || and && will short-circuit when one of the operands - evaluating from left-to-right - can determine the result of the expression, without reference to the remaining operands.
In the case of ||, this means that if the first operand is true, the remaining operands aren't evaluated, because the result of the entire expression will always be true.
In the first loop, the variable recheck - that is local to main - is always true, and so the function call test never needs to be evaluated: it is skipped, and you see no output.
In the second loop, the test function call is evaluated first, and it's result can only be determined after calling the function, so the function is called on each iteration, and you see the output.
Your comment says:
it is important that result's value is opposite to initial value of recheck in main()
Your test() function currently can't see the value of recheck, which is local to main().
Assuming your comment reflects your intent, you need to pass recheck as a parameter to test(); you can then use the unary ! operator, something like:
result = ! recheck;
And of course you need to fix the logic in main() so that test() is called when you need it to be.
Your requirements aren't clear enough for me to comment further.
Others have addressed the specific issue that you have raised. Just a note to say that beware of using multiple question marks in a row. Trigraph sequences start with two '??' characters and the third character after two question marks is interpreted differently.