Consider the following examples:
int x;
if (x = 1)
//...
if (std::cout << "Is it true?")
//...
Both are evaluated as true, but why?
The if (x = 1) is essentially the same as tmp = (x = 1); if (tmp) ...
The "result" of operator << (const char *) is an ostream&, which has an operator bool that the compiler calls to make it "comparable". operator bool will return "false if there was an error, otherwise true". Before C++11, it would return a void*, but the meaning was the same ("false (= 0) if there is an error, true otherwise".
The result of assignment is its left operand, so the value of x = 1 is its left operand x, which has the value of 1 now. And any non-zero integer is treated as true in the condition.
Because x = 1 is an assignment setting x to 1, not a comparison for equality. Comparison is done via x == 1.
It is a common mistake. Often people write 1 == x to catch these errors, since assignment to a constant triggers a compile-time error.
Besides the assignment result for x as mentioned in the other answers the
if (std::cout << "Is it true?")
evaluates to true, because the statement is equivalent to
if ((std::cout << "Is it true?").good())
which checks for the stream state of std::cout.
Both statements return a value other than 0 and are thus considered to be "true".
If you assign a value to a variable, the result of that statement is the assigned value so you can assign multiple variables at once. For example, foo = bar = baz = 1. This works because baz = 1 yields 1, which is then assigned to bar, then to foo. So x = 1 has the value 1 and is thus true.
Next, the std::cout << "foo": the operator<< on a ostream returns the ostream so you can do things like std::cout << "foo" << "bar";. Again, there is a value returned that is not 0 and thus true.
In this condition x = 1 you firstly assign 1 to your x variable, and then test x, so it is exactly the same with:
x = 1;
if( x ) // which is 1, so true
About the output operator <<, the compiler will return true if the output-stream's state cout is ok. So it is not going to be a valid stream if some error occurs.
In the first one, you're assigning the value of 1 to x. A non-zero value will always evaluate to true in a condition.
For the second one, when std::cout << "Is it true?" is called, operator<< will return a reference to std::cout. At that point, the condition is simply reduced to:
if (std::cout)
//
This is now evaluating whether or not std::cout is in a good state.
Related
I have these lines of code:
int a = 10, b = 1;
a = --b ? b : (b = -99);
cout << "a= " << a << "b= " <<b<< endl;
the output gives me b=-99 as a is not equal to 0(which makes senses) but it also changes the value of a to a=-99 how?
Your code is the equivalent of:
int a = 10, b = 1;
b -= 1; // b == 0
int x;
if (b != 0) x = b;
else x = b = -99;
a = x;
// at this point a and b have the same value
The ternary operator works as follows:
if (--b != 0) { // b is not 0 means true
a = b;
} else { // b is 0 means false
a = (b = -99);
}
You assign the value to a, so --b is 0 which is considered as false. Then you assign to b value -99 and afterward, you assign b to a. So, both variables have their values -99 in the end. Hope it will help you.
According to ternary operator, The first argument is a comparison argument(condition), the second is the result upon a true comparison, and the third is the result upon a false comparison.
So In Your case, the condition is not True, So the false statement get executed.
so now b has -99.
In c, c++, java we've seen, assigns the value of the variable
a = b = -99
In this, the both a & b gets the same value. Like this, ternary operator also assigning the value of the variable from false statement .
(a = (b = -99 ))
I think what is confusing you here is that, in C, an expression (such as b = -99) has both consequences and a value. The consequence of b = -99 is that b is assigned the value of -99; but note also that the value of this expression is -99.
Thus, in a ternary expression, which takes the general form:
lhs = test ? v_if_true : v_if_false;
the expression test is first evaluated and lhs is assigned either v_if_true (if test evaluates to non-zero) or v_if_false (if test evaluates to zero).
In your case, test is --b. The consequence of this expression is that the value of b is decreased by one, and the value of the expression is the resulting (modified) value of b (which will be zero in your code).
So, your ternary expression assigns to a the value of the v_if_false expression which is b = -99 (the brackets you give add clarity to the expression, but don't change its evaluation). So, as mentioned above, this expression (as well as modifying b) also has a calculated value of -99, which is then given to a.
If you wanted to leave a unchanged in the case when the v_if_false expression is executed, then you could do this using the comma operator, as follows (though I would not recommend using such code):
a = --b ? b : ((b = -99), a); // If --b == 0, this becomes a = a
This works because the value of an expression containing the comma operator is the value of the sub-expression after (to the right of) the comma.
If I use assignment operators or output functions inside the if condition, why is it taken as a "true" Boolean value?
For example, I do
if(cout << "a"){cout << "c";}
Or
if(int x=7){cout << "c";}
Or even
if(6){cout << "c";}
the outputs are indeed, "c" and "c" and "c" in each case. But we were told that, inside the if condition, we have to use an expression that finally evaluates to a Boolean value, like 1 or 0.
So what is the piece of information I am missing?
In each case the expression is converted to a bool. The value of this bool is true in the three cases that you use (it may not always be true).
if(cout << "a"){cout << "c";}
In this case the expression:
cout << "a"
If find the operator<<(std::ostream&, char const*) definition you will find that the return value is std::ostream&. So this will return a reference to the cout object (of type std::ostream). The stream object has a boolean conversion method explicit bool() which can be used to convert the object to bool. The result of this depends on the state of the object (if it is in a bad (failing) state it will return false).
So here you are checking that the last operation on the stream worked. If it does then print "c". This is commonly used on input streams to validate user intput.
int val;
if (std::cin >> val) {
if (std::cout << "A value was correctly read\n") {
// Add response worked.
}
else
{
// Something bad happened to std::cout
}
}
In the other cases you use int variables. These can be implicitly converted to bool. If the value is non zero then it is true (otherwise false).
Every value inside a condition (or with Boolean conversion) will give you true, unless it equal to 0.
(6) returns => 6 != 0 => true
(x = 7) returns => 7 != 0 => true
(cout << "aa") returns => ostream object.
bool context so calls `ostream::operator bool()`
If the stream is in good state => true
Otherwise => false
In C you can see it with NULL with this declaration:
#define NULL 0
which means that if an pointer equal to NULL it will return you a false in a Boolean conversion.
Examples in C++ for boolean expressions:
int a, b, *c;
char d;
bool e;
a = 0;
b = 2;
c = nullptr;
e = a; // false
e = b - 2; // false
e = c; // false
c = &a;
e = c; // true
e = b; // true
e = a + 1; // true
e = b ^ b; // false
d = 0;
e = d; // false
d = '0';
e = d; // true
In all the cases you've shown, it's still true that you've provided an expression that eventually is convertible to bool. If you look at the << operator of std::cout and similar ostreams, you'll see they all return a reference to the same stream. This stream also defines a conversion to bool operator, which is implicitly called in a context where a bool is expected. This particular conversion returns true if the stream has no errors. Secondly, int x=7 is an initialization, and it returns the value that x was just initialized with; 7 in this case. int in C++ can be implicitly cast to bool to be true if it's not zero, which is why both 7 and 6 evaluate to true in the second and third examples.
return model == DHT11 ? 0 : -40;
I believe it means "return model if between 0 and -40", but I'd like a definitive answer.
Its the ternary operator, equivalent to:
if (model == DHT11)
return 0;
else
return -40;
so it has nothing to do with a check for a range.
The ternary operator yields a value, i.e. you could also use this in an assignment like:
retval = model == DHT11 ? 0 : 40;
return retval;
This operator (E1?E2:E3) is called ternary operator, where E are expressions.
It means : "If E1 is true, return E2, else, return E3"
Here's a link to cppreference explaning a bit more.
As already mentioned, it is called the ternary operator.
The ternary operator checks to see if something is true, and if it is, yields the value before the :. If it is false, it yields the value after the :.
In this situation, it checks to see if model == DHT11 evaluates to true, and gives 0 if so. If model == DHT11 evaluates to false, it gives -40. The value the ternary evaluates to is then given to return, quitting the function, and returning either 0 or -40.
Other example:
std::string hi = "hi";
std::cout << (hi == "hi") ? "string hi contains \"hi\"." : "string hi does not contain \"hi\"." << "\n";
Would print:
string hi contains "hi".
General Syntax:
bool ? value1 : value2
The ternary operator is just like an if-else statement, compacted down to one line.
Here is a part of code
int main()
{
int x=5,y=10;
if(x=!y)
{
cout<<"h";
}
else
{
cout<<"p";
}
getch();
}
The output was p, please explain, how the code works and the meaning of x=!y.
Looks like a typo that produces valid code. Expanding it helps--
if (x = (!y))
Since y is 10, !y == 0, and assignments themselves produce a value. In particular the value of x = 0 is 0, so the test evaluates to 0 and that's why you get the result.
But this is a crazy thing to write in this context, presumably what was, or what should have been intended was
if (x != y)
I.e., not-equals.
x=!y is an assignment.
x is being assigned the value of !y expression, which is a logical "NOT" operation. This operation returns true if the operand is zero, or false otherwise. The value true becomes 1 when assigned back to int; false becomes zero.
In C and C++ it is OK to use assignment expressions inside if conditionals and other control statements, such as for and while loops. The value being assigned is used to evaluate the condition, and the assignment itself is performed as a side effect. In this case, the condition is !y.
string temp is equal to "ZERO:\t.WORD\t1" from my debugger. (the first line of my file)
string temp = RemoveWhiteSpace(data);
int i = 0;
if ( temp.length() > 0 && isalpha(temp[0]) )
cout << "without true worked" << endl;
if ( temp.length() > 0 && isalpha(temp[0]) == true )
cout << "with true worked" << endl;
This is my code to check if first character of temp is a a-z,A-Z. The first if statement will evaluate to true and the 2nd to false. WHY?!?!?! I have tried this even without the "temp.length() > 0 &&" and it still evaluates false. It just hates the "== true". The only thing I can think of is that isalpha() returns != 0 and true == 1. Then, you could get isalpha() == 2 != 1. But, I have no idea if C++ is that ... weird.
BTW, I dont need to know that the "== true" is logically pointless. I know.
output was
without true worked
Compiled with CodeBlock using GNU GCC on Ubuntu 9.10 (if this matters any)
The is* functions are only guaranteed to return a non-zero value if true, NOT necessarily a 1. A typical implementation is table based, with one entry in the table for each character value, and a set of bits defining which bit means what. The is* function will just AND the right bitmask with the table value, and return that, which will only be the value 1 for whichever type happens to have been given bit position 0.
E.g.:
#define __digit 1
#define __lower 2
#define __upper 4
extern int __type_table[];
int isdigit(int c) {
return __type_table[c+1] & __digit;
}
int isalpha(int c) {
return __type_table[c+1] & (__lower | __upper);
}
int islower(int c) {
return __type_table[c+1] & __lower;
}
int isupper(int c) {
return __type_table[c+1] & __upper;
}
Where __type_table is defined as something like int __type_table[UINT_MAX+1]; and would be initialized so (for example) __type_table['0'+1] == __digit and __type_table['A'+1] == __upper.
In case you care, the '+1' part is to leave a spot at the beginning of the table for EOF (which is typically defined as -1).
isalpha doesn't return true, it returns non-zero. This is quite common for API designed for C.
Note that in the expression isalpha(ch) == true, the subexpression true is promoted to type int with value 1.
Well, the documentation suggests that it returns either zero or non-zero, not necessarily just false or true. So you'd better check (isalpha(temp[0]) != 0).
Do not isalpha(ch) == true, but !!isalpha(ch) == true