I had a question in my test paper in which we had to compare the values of int type variables. The first thought that came to my mind was that it was missing the && operator but i am not sure.
int a=2, b=2, c=2;
if(a==b==c)
{
printf("hello");
}
I have a doubt, will the above statement will execute or not in c or c++? Can i have the reason as well.
Thank You
It will execute but with what I believe unexpected results to you.
One of the == will evaluate to a boolean value, which will then be converted to an int and then the second comparison will be performed, comparing an int to either 1 or 0.
The correct statement is a==b && b==c.
For example:
3 == 3 == 3
evaluates to
true == 3
1 == 3
false
a==b==c
is equivalent to
(a == b) == c
The result of a == b is 1 (if true) or 0 (if false), so it will probably not achieve what you expect.
Use a == b && b == c to check if the value of the three objects are equal.
a == b == c is a comparison between c and result of a==b (1 or 0) operation.
use a==b&&b==c.
the condition a==b==c is equivalent to (a==b)==c which will provide the required result iff c==1, else the code will fail.
Related
I have some code in an old desktop app, which I inheritted from a colegue who left the company.
Here is a short similar example of the actual code I have:
#include <iostream>
int getType(int type)
{
return type;
}
int main()
{
int variable1 = 30;
int variable2 = 40;
int result = (getType(30) == (variable1 || variable2) ? 1 : 2);
std::cout << result << std::endl;
}
For the result I always receive 2, not 1 as I expected.
If I try:
int result = (getType(30) == (variable1) ? 1 : 2)
the result is true.
I can't figure out why this part:
int result = (getType(30) == (variable1 || variable2) ? 1 : 2)
is not true...
In the initializer expression of this declaration
int result = (getType(30) == (variable1 || variable2) ? 1 : 2);
the subexpression (variable1 || variable2) has the type bool and its value is true (variable1 isn't 0 so that is true) that is implicitly converted to the integer value 1 in the expression with the equality operator (getType(30) == (variable1 || variable2) .
From the C++17 Standard (7.6 Integral promotions)
6 A prvalue of type bool can be converted to a prvalue of type int,
with false becoming zero and true becoming one.
So as getType(30) is not equal to 1 the result of the initializer expression is 2.
To get the expected result you should rewrite the declaration like
int result = (getType(30) == variable1 || getType(30) == variable2) ? 1 : 2;
I think perhaps your understanding of the || operator is not quite right. The || operator is the or operator, and it will return a boolean result, false or true. In your code, you are doing this comparison: getType(30) == (variable1 || variable2). The parenthesis get evaluated first because of order of operations and you end up with getType(30) == true, since variable1 has a non-zero value. getType(30) evaluates and returns 30, so the expression is 30 == true. The true value then gets coerced to a 1 because of the rules of c++ and we evalate 30 == 1 which is false.
I think what you are asking for is why this doesn't do what you expect. And I see two problems, the one is that the getType function doesn't actually do what you might expect, it simply returns the variable. I'm not sure what you would expect in c++, but that's definitely a problem. The other expectation is probably that you want to compare the return of getType(30) with both variable1 and variable2 which would require a longer expression. The expression you want is probably getType(30) == variable1 || getType(30) == variable2. This is a common problem because in english we say 'if gettype equals var1 or var2`, but it doesn't translate into code like that unfortunately.
if ((pCommandPts>=tempChar.commandValue) && ((pCommandPts - tempChar.commandValue)<=0))
If pCommandPts is an int with the value 6 and tempChar.commandValue is an int with the value 3, why would this statement evaluate to false?
Left part of this expression is true in case of 6 and 3, but 6-3 is not lower or equal to zero
&& ((pCommandPts - tempChar.commandValue)<=0))
That code makes no sense, and it's almost certainly a bug.
If you rearrange the inequalities, you get:
a >= b && a <= b
Which is only true if a == b, which is not true for your case 6 != 3
This question already has an answer here:
The Definitive C++ Book Guide and List
(1 answer)
Closed 7 years ago.
I'm less than a year into C++ development (focused on other languages prior to this) and I'm looking at a guy's code who's been doing this for two decades. I've never seen this syntax before and hopefully someone can be of some help.
bool b; // There exists a Boolean variable.
int i; // There exists an integer variable.
sscanf(value, "%d", &i); // The int is assigned from a scan.
b = (i != 0); // I have never seen this syntax before.
I get that the boolean is being assigned from the int that was just scanned, but I don't get the (* != 0) aspects of what's going on. Could someone explain why this person who knows the language much better than I is doing syntax like this?
Have a read here:
http://en.cppreference.com/w/cpp/language/operator_comparison
The result of operator != is a bool. So the person is saying "compare the value in i with 0". If 'i' is not equal to 0, then the '!=' returns true.
So in effect the value in b is "true if 'i' is anything but zero"
EDIT: In response to the OP's comment on this, yes you could have a similar situation if you used any other operator which returns bool. Of course when used with an int type, the != means negative numbers evaluate to true. If > 0 were used then both 0 and negative numbers would evaluate to false.
The expression (i != 0) evaluates to a boolean value, true if the expression is true (i.e. if i is non-zero) and false otherwise.
This value is then assigned to b.
You'd get the same result from b = i;, if you prefer brevity to explicitness, due to the standard boolean conversion from numeric types which gives false for zero and true for non-zero.
Or b = (i != 0) ? true : false; if you like extraneous verbosity.
(i != 0) is an expression that evaluates to true or false. Hence, b gets the value of true/false depending on the value of i.
This is fairly fundamental syntax. The != operator performs a "not equal to" comparison.
You may be being confused by the shorthand of initialising a bool directly from the result of a comparison operator, but the syntax itself is not esoteric.
The program is essentially equivalent to:
bool b;
int i;
sscanf(value, "%d", &i);
if (i != 0)
b = true;
else
b = false;
The key is that i != 0 is itself an expression that evaluates to true or false, not some magic that may only be used in an if statement.
Basically, if the condition (i not_equal_to 0 ) is satisfied, b gets the value "true". Else b gets the value "false".
Here, "i != 0" is a boolean expression that will be true if "i" is non-zero and false if it is zero.
All that is happening here is the result of that expression is being assigned to a variable.
You could also do things like...
boolean canDrinkAlcohol = (person.age() >= 18 && person.country.equals("UK") || person.age() >= 21 && person.county.equals("US"));
...
if(canDrinkAlcohol) {
...
}
or something
I didn't think these if's would compile but they do:
if (a>>b&&c&&d)
if (month==1,2,3,5,7,9,10)
The first I'm clueless about. In the second statement is the comma supposed to be an (||) or operator ?
Syntax wise was it always this way or was it introduced some time ago ?
I'm using Visual Studio 2010.
if (a>>b && c && d)
it is equal to
if ((a>>b) && c && d)
if the result of a shifted right b times evaluates to a bool, c and d also evaluates to bool respectively, then all these booleans will be AND-ed to each other.
In your context, the all expressions within commas will be evaluated and then the last expression will be passed to if expression:
if (month==1,2,3,5,7,9,10) -> is equal to
if (2,3,5,7,9,10) -> is equal to
if (3,5,7,9,10) -> is equal to
if (5,7,9,10) -> is equal to
if (7,9,10) -> is equal to
if (9,10) -> is equal to
if (10)
which is always true.
It's not suppose to be || or &&. If you want OR or AND write it like below:
if (month==1 || month==2 || month==3 || ....)
or
if (month==1 && month==2 && month==3 && ....)
// Also month can not simultaneously be equal to more than one value!
// then, it's equal to
if (false)
The first if statement would be evaluated like:
if(((a >> b) && c) && d)
Essentially bitshift a by b bits and then logical and with c and then with d
The second is the comma operator which will evaluate the first term and throw it away, then the second, and so on and return the result of the final term. So in our case the statement is equivalent to:
if(10)
which is always true.
Unthinkingly I wrote some code to check that all the values of a struct were set to 0. To accomplish this I used:
bool IsValid() {
return !(0 == year == month == day == hour == minute == second);
}
where all struct members were of type unsigned short. I used the code as part of a larger test but noticed that it was returning false for values differing from zero, and true for values that were all equal to zero - the opposite of what I expected.
I changed the code to read:
bool IsValid() {
return (0 != year) || (0 != month) || (0 != day) || (0 != hour) || (0 != minute) || (0 != second);
}
But would like to know what caused the odd behaviour. Is it a result of precedence? I've tried to Google this answer but found nothing, if there's any nomenclature to describe the result I'd love to know it.
I compiled the code using VS9 and VS8.
== groups from left to right, so if all values are zero then:
0 == year // true
(0 == year) == month // false, since month is 0 and (0 == year) converts to 1
((0 == year) == month) == day // true
And so on.
In general, x == y == z is not equivalent to x == y && x == z as you seem to expect.
The behaviour shouldn't be seen as odd. The grammar rules for == (and most but not all binary operators) specify left to right grouping so your original expression is equivalent to:
!((((((0 == year) == month) == day) == hour) == minute) == second)
Note that when compared to an integer type a bool expression with value true will promote to 1 and with value false will promote to 0. (In C the result of the equality operator is an int in any case with a value or either 1 or 0.)
This means that, for example, ((0 == year) == month) will be true if year is zero and month is one or if year is non-zero but month is zero and false otherwise.
You have to consider how it's evaluated...
a == b == c
is asking if two of them are equal (a and b), then comparing that boolean result to the third value c! It is NOT comparing the first two values with the third. Anything beyond 2 arguments won't chain as you evidently expect.
For whatever it's worth, because C++ considers non-0 values to be "true" in a boolean context, you can express what you want simply as:
return year && month && day && hour && minute && second;
(note: your revised code says "month" twice and doesn't test minute).
Back to the chained ==s: with user-defined types and operator overloading you can create a class that compares as you expect (and it can even allow things like 0 <= x < 10 to "work" in the way it's read in mathematics), but creating something special will just confuse other programmers who already know the (weird) way these things work for builtin types in C++. Worth doing as a ten/twenty minute programming exercise though if you're keen to learn C++ in depth (hint: you need the comparison operators to return a proxy object that remembers what will be the left-hand-side value for the next comparison operator).
Finally, sometimes these "weird" boolean expressions are useful: for example, a == b == (c == d) might be phrased in English as "either (a == b) and (c == d), OR (a != b) and (c != d)", or perhaps "the equivalence of a and b is the same as the equivalence of c and d (whether true or false doesn't matter)". That might model real world situations like a double-dating scenario: if a likes/dislikes b (their date) as much as c likes/dislikes d, then they'll either hang around and have a nice time or call it quits quickly and it's painless either way... otherwise one couple will have a very tedious time of it.... Because these things can make sense, it's impossible for the compiler to know you didn't intend to create such an expression.
Your error here is writing a mathematical expression using equals signs, and unthinkingly supposing that the computer will perform the test you meant - what a human mathematician would see as the meaning of those symbols. What the computer does (as per the definition of the language) is to perform a series of discrete comparisons, each of which returns true or false - and this true or false is then used in the next comparison. You aren't comparing all of those variables to 0, you're comparing each (bar two of them) to the result of comparing another two of the said variables.
The return of the == operator is 1 if the operands are equal, so regardless wether this is read from left to right or right to left, this will not do what you expect.
so this could only work in an analogous test if you would be interested if all values are 1.
And to have a shorter expression since you seem interested in that just do year || day || ...