The output should be false, as false&&true is false. However, the compiler is giving 1 as output.
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int b = 13;
bool flag = true;
cout << ((b - 4) < a) && !flag;
return 0;
}
This is because << has higher precedence than &&, your expression should be:
cout << (((b-4)<a) && !flag);
A more detailed explanation:
One of the first things that any C++ compiler does when processing your source code is to construct an abstract syntax tree (AST) representing your source code. The AST is a tree structure that encodes -among other things- the precedence of different unary and binary operators. An AST for the expression you have written (cout << ((b - 4) < a) && !flag;) would look something like this:
&&
/ \
<< !
/ \ \
cout < flag
/ \
- a
/ \
b 4
How do we know that e.g. && must be the root of the AST or that sub-expressions in parentheses are evaluated first? Because the C++ operator precedence rules say so. These are similar to the rules we use when doing math on paper (e.g. do multiplication before addition) but extended to all operators supported by the language.
We can use the AST to see in what order the sub-expressions of this expression are evaluated, the general rule being that evaluation happens in "bottom up" order, i.e. from the leaves to the root of the AST. In this particular case, evaluation could (conceptually) happen like this:
// left subtree
b - 4 = 9
9 < a = true
cout << true = cout (operator<< returns a reference to cout)
// right subtree
!flag = false
And finally we're left with cout && false. cout implements operator bool which allows it to be implicitly cast to bool, yielding true if the stream has no errors. Because that is the case here, we finally have true && false == false the value of which is unused.
So you can see that your program outputs 1 because during evaluation of the left subtree, cout << true is executed. Afterwards, cout && !flag, though well formed, essentially does nothing because it has no side effects and you don't use the result.
Related
I am currently learning from an SDL2/OpenGL2 example code, for ImGui. Then, I ran into a line (and a few more alike) as shown below. I believe this part binds SDL mouse events to IMGUI API. However, I do not quite understand how it works.
io.MouseDown[0] = g_MousePressed[0] || (mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0
where,
ImGuiIO& io = ImGui::GetIO();
bool mouseDown[5]; // a member of ImGuiIO struct
static bool g_MousePressed[3] = { false, false, false };
Uint32 mouseMask = SDL_GetMouseState(&mx, &my);
(I hope above is enough information...)
What makes me the most confused is the the last part, not equal to 0. I could understand it, if it was a simple assignment of the result of an And and an Or operations. However, there is not equal to zero following at the end and I have not seen this before. I would like to get some help to understand this code please.
expression != 0
is a boolean expression and thus evaluates to either true or false which can be converted to integer values of 0 or 1.
#include <iostream>
int main() {
constexpr size_t SDL_BUTTON = 5;
for (size_t mouseMask = 0; mouseMask < 16; ++mouseMask) {
std::cout << mouseMask << ' '
<< (mouseMask & SDL_BUTTON) << ' '
<< ((mouseMask & SDL_BUTTON) != 0) << '\n';
}
}
Live demo: http://ideone.com/jcmosg
Since || is the logical or operator, we are performing a logical comparison that tests whether io.MouseDown != 0 or (mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0 and yields a boolean value (true or false) promoted to whatever type io.mouseDown[0] is.
The code could actually have been written as:
io.MouseDown[0] = g_MousePressed[0] || (mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT))
or
const bool wasPressed = g_mousePressed[0];
const bool newPress = mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT);
const either = (wasPressed == true) || (newPress == true);
io.MouseDown[0] = either;
or
if (g_mousePressed[0])
io.MouseDown[0] = 1;
else if (mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT))
io.MouseDown[0] = 1;
else
io.MouseDown[0] = 0;
See http://ideone.com/TAadn2
If you are intending to learn, find yourself a good sandbox (an empty project file or an online ide like ideone.com etc) and teach yourself to experiment with pieces of code you don't immediately understand.
An expression a = b || c!=0 means a = (b!=0) || (c!=0). In boolean logic, b and b!=0 are equivalent. That's what I think the most confusing part. Once this is understood, there should be no problem.
Note that this expression should not be confused with a=b|c!=0, where | is a binary operation called "bit-wise or", as opposed to the logical operation ||, which is the logical "or". When doing b|c!=0, c!=0 is calculated first to yield a logical value 0 or 1, then b|0 or b|1 is calculated to do nothing (first case) or reset the last bit of the binary code of b to 1 (second case). Finally, that result is assigned to a. In this case, b and b!=0 are not equivalent, because the bit-wise or | is used instead of the logical or ||.
Similarly, & is the "bit-wise and" operator, while && is the logical "and". These two should not be confused either.
Notice that != has a higher precedence than ||, so the whole expression is indeed a simple assignment of the result of an OR.
The !=0 part is a way to turn the result of applying a bitmask into bool, as #AlekDepler said. Funny thing is its pretty much redundant (if mouseMask is of built-in integral type) as implicit conversion from say int to bool works exactly like !=0.
#include<iostream>
int main()
{
int a = 5;
a = (a = 10, a++, a--);
std::cout << a;
}
Output is 11,
But when I modify the line
a = a=10,a++,a--;
Output is 10
What effect does removing the ( ) operator has and in what order the operators are being executed.
The + and - operators take precedence before the assignment operator and the +,- signs are read by the compiler from left to right, whereas the assignment operators are read by the compiler from right to left. So:
1) a++
2) a--
3) a=10
4) a =
The c++ compiler will pass your complete set code to a binary tree which will rearrange your code according to the precedence of the operator = + - etc in left node or right node
Is it possible to write a one line if-else statement (i.e. only using one ;) without using the ?: expression? For instance something of the form:
if (p == 1) " " else "\n";
Potential purpose could be:
cout << if (p == 1) " " else "\n";
Just curious if this is possible, don't know if there are any practical applications for this.
Thanks
You're asking "how do I do X, without using any of the tools the language provides to do X". It's silly.
And the answer's no. It's not possible.
This doesn't address the general question, but it does work for the specific example you provided.
std::cout << " \n"[(bool)(p - 1)];
Explanation:
First, a string literal (such as " \n") is an array. As such, it participates in pointer decay, and can be indexed just like any other pointer or array.
Second, an integer can be converted to a bool, and the conversion has the special property that a zero is converted to false, and anything else is converted to true. So when I subtract 1 from p, then convert it to bool, it is false if p is 1, and true otherwise.
Third, a bool can be (implicitly) converted back to an integer. false converts to 0, and true converts to 1. So converting from an int to a bool and back has the result that a 0 stays a 0, and anything else becomes a 1.
So, with those three points taken into consideration, the expression:
" \n"[(bool)(p - 1)]
results in one of these two possibilities:
" \n"[0] // a space (if p == 1)
" \n"[1] // or a newline (if p != 1)
I'd downvote this answer if I could.
You already used the two important words that are key to undestand why what you intend is not possible, but you probably haven't grasped their full meaning: Statement and expression.
The if statement (like all statements) does not yield a value, while the ?: operator is an expression that does yield a value.
Distinguishing between statements and expressions is a fundamental concept that is worth learning (check out the links in this answer and take your time!), not just for C++ but for almost all programming languages.
cout << [=]{ if (p == 1) return " "; else return "\n"; }();
Basically: no, it's not possible to do this:
cout << if (p == 1) " " else "\n";
That is exactly the purpose of ?: operator - it yields value. Some things may not be possible with if-else syntax. Example: conditional initialization. Consider:
if(p == 1)
int value = 1; //local variable!
else
int value = 0; //and so is this one!
//here 'value' is unknown
Above problem could be solved this way:
int value; //default initialization
if(p == 1)
value = 1; //assignment to already initialized variable!
else
value = 0; //and so is this!
But these two are not equal. For some types, it may result in totally different behavior, because initialization is different from assignment. ?: is a solution:
int value == (p == 1) ? 1 : 0; //'value' is initialized with value, that depends on 'p'
Do not try to do things without tools, that were designed to do that things for you.
I have a sample midterm question that I am not too sure about. Here it is:
#include <iostream.h>
void f( int i )
{
if( i = 4 || i = 5 ) return;
cout << "hello world\n" ;
}
int main()
{
f( 3 );
f( 4 );
f( 5 );
return 0;
}
So I understand that the logical OR operator has a higher precedence and that it is read left to right. I also understand that what's being used is an assignment operator instead of the relational operator. I just dont get how to make sense of it all. The first thing the compiler would check would be 4 || i? How is that evaluated and what happens after that?
Let's add all the implied parentheses (remembering that || has higher precedence than = and that = is right-associative):
i = ((4 || i) = 5)
So, it first evaluates 4 || i, which evaluates to true (actually, it even ignores i, since 4 is true and || short-circuits). It then tries to assign 5 to this, which errors out.
As written, the code doesn't compile, since operator precedence means it's i = ((4 || i) = 5) or something, and you can't assign to a temporary value like (4 || i).
If the operations are supposed to be assignment = rather than comparison == for some reason, and the assignment expressions are supposed to be the operands of ||, then you'd need parentheses
(i = 4) || (i = 5)
As you say, the result of i=4 is 4 (or, more exactly, an lvalue referring to i, which now has the value 4). That's used in a boolean context, so it's converted to bool by comparing it with zero: zero would become false, and any other value becomes true.
Since the first operand of || is true, the second isn't evaluated, and the overall result is true. So i is left with the value 4, then the function returns. The program won't print anything, whatever values you pass to the function.
It would make rather more sense using comparison operations
i == 4 || i == 5
meaning the function would only print something when the argument is neither 4 nor 5; so it would just print once in your example, for f(3).
Note that <iostream.h> hasn't been a standard header for decades. You're being taught an obsolete version of the language, using some extremely dubious code. You should get yourself a good book and stop wasting time on this course.
The compiler shall isuue an error because expression 4 || i is not a lvalue and may not be assigned.
As for the expression itself then the value of it is always equal to true because 4 is not equal to zero.
I am writing library which allows some function programming operations on ranges. Ranges are generalization of STL containers. My question is what result of folding for empty range should be?
auto r = range(4); // lazy numeric range {0,1,2,3}
auto r0 = range(0); // empty range {}
vector<string> vs {"a", "bb"};
vector<string> vs0 {};
// this is obvious and implemented part
cout << (r || add); // 6, || - folding op
cout << (r0 || add); // 0
cout << (vs || add); // "abb"
cout << (vs0|| add); // ""
cout << (r || mul); // 0
cout << (r0 || mul); // 1
cout << (r || max); // 3
// What result of these should be?
cout << (r0 || div); // ???
cout << (r0 || sub); // ???
cout << (r0 || max); // -∞ ???
cout << (r0 || min); // +∞ ???
cout << (r0 || ???); // result of arbitrary op?
EDIT - ANSWER
http://en.wikipedia.org/wiki/Identity_element
I assume your "folders" are instances of some template, with a binary function attached and maybe an initial value.
Traditionally, fold is defined as recursively calling said binary function on (initial, first), then (old value, next) until you run out of stuff to call it on.
There is no such initial value such that subtraction and division work the way you might expect them to (such that fold({1,2}) is 1/2).
Thus "folders" of subtraction and division are either "sums of inverse" and "product of inverse" (ie, fold(r) = 1/fold(r), and fold(r) = -fold(r), which seems pretty boring), or they are fundamentally different things that don't work on empty containers.
max and min should clearly generate the highest and lowest value for a given type, or be the folders of the second type that do not make sense on empty containers.
By "not work", they could throw an exception, or they could return something like a boost::optional<T> -- ie, on an empty list, they do not return anything.
Your folder type could take a function which finds the initial value for a given type, which should resolve to a traits template class or a free function (similar to std::begin).
...
Edit: from the comments below, an improvement to the answer.
The real trick here is that there is no left-hand identity for subtraction and division But there is a right hand identity!
Operations that only have a right hand identity should be expressed as right-hand folds, and operations that only have a left hand identity should be expressed as left-hand folds (aka, foldr and foldl)
Ie, the natural way to express a fold on a list {a,b,c} with identity id of binary operation *op* is:
( (id *op* a) *op* b ) *op c
but for operations without a left-hand identity, this doesn't work.
However, if you reverse the fold handedness, you get this:
a *op* (b *op* (c *op* id))
which works so long as you have a right-hand identity.
This is important for div and sub -- div has a right-hand identity of 1, and sub has a right-hand identity of 0, but neither has a left-hand identity. (there is no element e such that e-x = x for all x. There is an element e such that x-e = x for all x, namely 0).
The same is true of exponentiation (which has a right-hand identity of 1, but no left-hand identity).
This still doesn't match what a naive expectation of what fold div should do. It works on lists of length 2, but on lists of length 3 something unintuitive happens. But at least it is mathematically sound. :)