Result of value comparison in c++ - c++

In the following piece of code the output is 1 but I'm not sure why. Has i been implicitly changed to a boolean? How can an integer value be set to an expression like this?
#include <iostream>
using namespace std;
int main (int argc, const char *argv[])
{
int a = 1, b = 1, c = 1, i = 1;
i = b < a < c;
cout << i;
return 0;
}

Has i been implicitly changed to a boolean?
No. Rather, a boolean expression has been implicitly converted to int, then stored in i, as commented by #WhozCraig.
How can an integer value be set to an expression like this?
Because it follows the C++ Standard.
When you do:
i = b < a < c;
since the first < and the second < have the same operator precedence (since they are the same operator), so:
Operators that have the same precedence are bound to their arguments
in the direction of their associativity. For example, the expression a
= b = c is parsed as a = (b = c), and not as (a = b) = c because of right-to-left associativity of assignment, but a + b - c is parsed (a > + b) - c and not a + (b - c) because of left-to-right associativity of addition and subtraction.
as mentioned in C++ Operator Precedence, which means that this expression of yours will be parsed as if it was written like this:
i = (b < a) < c;
which will evaluate the condition inside the parentheses, which is False.
Now bool to int conversion is implicit:
§4.7/4 from the C++ Standard says (Integral Conversion)
If the source type is bool, the value false is converted to zero and the value true is converted to one.
which means that false will be converted to 0, and then we basically end up doing:
i = 0 < c;
which evaluates to true, since c is equal to 1. Now i is of type int, which means that another, second implicit conversion from boolean to integer takes place, eventually assigning 1 to i.

Related

Can we assign the result of a logical expression to an integer variable?

I searched about this issue but the answer I found was that the result of a logical expression cannot be assigned to an integer variable it can be only assigned to a boolean variable, but then I tried a simple code to check my point that the result can be assigned to an integer variable because in the first place the logical expression returns an integer value.
#include <iostream>
using namespace std;
int main() {
int n1 = 1;
int n2 = 2;
int b;
b = (n1 == n2);
cout<<b;
}
Basically is this case the result of the logical expression is false which means it's 0
So why is it wrong to store the result in an integer value??
Here's one of the websites
Here's another one
when you say:
b = (n1 == n2);
the compiler says:
b = int(n1 == n2);
this concept is known as implicit type conversion.

Not able to understand the working of Pre-increment/ Pre-decrement in C++

Can someone please explain what is happening in the following code? (Taken from GeeksForGeeks)
int main(){
int a = 10;
++a = 20; // works
printf("a = %d", a);
getchar();
return 0;
}
What exactly is happening when the statement ++a = 20 is executed? Also, please clarify why this code fails in execution?
int main(){
int a = 10;
a++ = 20; // error
printf("a = %d", a);
getchar();
return 0;
}
Code Taken From: http://www.geeksforgeeks.org/g-fact-40/
When you do
++a = 20;
it's roughly equivalent to
a = a + 1;
a = 20;
But when you do
a++ = 20;
it's roughly equivalent to
int temp = a;
a = a + 1;
temp = 20;
But the variable temp doesn't really exist. The result of a++ is something called an rvalue and those can't be assigned to. Rvalues are supposed to be on the right hand side of an assignment, not left hand side. (That's basically what the l and r in lvalue and rvalue comes from.)
See e.g. this values category reference for more information about lvalues and rvalues.
This is the difference between r and l values. If you would have compiled the 2nd code snippet with gcc you would have seen this:
lvalue required as left operand of assignment
meaning, that a++ is rvalue and not a lvalue as it should be if you want to assign something to it
int main(){
int a = 10;
++a = 20; // works
printf("a = %d", a);
getchar();
return 0;
}
This is a c Language.
Explaining Line by line
int main() THIS line define an entry function called main which is expected to return a type integer(int)
int a = 10 declares a variable integer whose value is 10;
++a = 20; AT this point your code is incrementing the value of a by 1 before any operation is performed on a.
This means that, the value of a is incremented by 1 bfore a is assign the value of 20;....
the statement ++a = 20 is incorect in the sense that, a is 10 initially, and you increment it to 11 . Is like saying 11 = 20; this may not throw an error because the code line is not useful.
printf() is a c-method to print file to screen, passing a string "a = %d" tells the compiler to print a to a decimal number(%d).
getchar() is use to terminate the running program and return 0 is to forcefully tell the operating system that the code run successfully and return integer value 0.
int main(){
int a = 10;
a++ = 20; // error
printf("a = %d", a);
getchar();
return 0;
}
This didn't at a++ = 20 because , right value increment perform the operation before it increment unlike ++a who increment before performing operation.
So this isn't possible and it never works because a is already 10, and you are saying the value ++ and assign 20, you can't assign a value to it, it should be the one calculating its own value. So the compiler will want to interprete is as variable a++ = 20, and ++ can not be a vaiable name. That's why it never work.
What is the essence of incrementation and decrementation in c....its useful for creating conditional statement e.g for loop, while statement etc. for example:
for(int i = 0; i < 4; i++)
{
printf('THis is c-language');
}
or
int i = 0;
while(i < 4){
printf('THis is c-Language');
i++;
}
so therefore, following the programming rules and regulations, you are not allow to assign value to either a++ or ++a
they are for the compilers to manipulate, so never assign value to them.
Thank you.
The left operand of the assignment operator should be an lvalue.
The expression ++a is an lvalue while a++ is not and therefore it can't be the left operand of the assignment operator.
n3797-§ 5.3.3(p1):
[...] The result is the updated operand; it is an lvalue [...]

Adding `bool` to `float`

I'm maintaining some code and came across this snippet:
int num = 0;
float sum = 0.0;
bool value[rows][cols]; //initialized elsewhere in the code
for(int i = 0; i < rows; i++)
for(int j = 0; j < cols; j++)
if(value[i][j] == true) {
sum += value[i][j]; //shouldn't this be equivalent to "sum += 1;"
//as it is in the if block?
num++;
}
float ans = 1.0;
if(num > 12)
ans = sum / num;
Is the guy who wrote this code originally doing something fiendishly clever here, or should ans always be 1? As far as I can tell, num and sum should always be exactly the same value, no?
This will the same as sum += 1 since a true value will be converted to 1 this is covered in the draft C++ standard section 4.9 Floating-integral conversions which says:
If the source type is bool, the value
false is converted to zero and the value true is converted to one.
The additive operators will cause the usual arithmetic conversions to be performed on their operands. Which in this case will be covered by this case:
Otherwise, if either operand is float, the other shall be converted to float.
and we know that E1 += E2 is equivalent to E1 = E1 + E2 from section 5.17 Assignment and compound assignment operators which says:
The behavior of an expression of the form E1 op = E2 is equivalent to E1 = E1 op E2 except that E1 is
evaluated only once.[...]
The answer is not fiendlishly clever because the if statement is still present.
To be clever, one would do something like this:
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
sum += value[i][j]; // Add 1 if true, 0 if false.
num += value[i][j]; // Add 1 (increment) if true, add 0 if false
}
}
The assumption is that a bool type will convert to 1 if true, and 0 if false. This is how things were done in the dawn of computers.
If the true evaluates to some nonzero value other than 1, this code will not work correctly.
Upon further analysis, the sum and num will have the same value at the end of the loops.
So, only use num and convert to float at the end of the loop.
If value is a (two-dimensional) array of bool, then this is equivalent with sum += 1. In contrast with what some people think, a comparison with == true is not the same as an implicit conversion to bool (e. g. in the context of an if statement's condition). Any integer not equal to 1 will be considered different from true.

Comparison signed and unsigned char

It seems so strange. I found misunderstanding. I use gcc with char as signed char. I always thought that in comparison expressions(and other expressions) signed value converts to unsigned if necessary.
int a = -4;
unsigned int b = a;
std::cout << (b == a) << std::endl; // writes 1, Ok
but the problem is that
char a = -4;
unsigned char b = a;
std::cout << (b == a) << std::endl; // writes 0
what is the magic in comparison operator if it's not just bitwise?
According to the C++ Standard
6 If both operands are of arithmetic or enumeration type, the usual
arithmetic conversions are performed on both operands; each of the
operators shall yield true if the specified relationship is true and
false if it is false.
So in this expression
b == a
of the example
char a = -4;
unsigned char b = -a;
std::cout << (b == a) << std::endl; // writes 0
the both operands are converted to type int. As the result signed char propagets its signed bit and two values become unequal.
To demonstrate the effect try to run this simple example
{
char a = -4;
unsigned char b = -a;
std::cout << std::hex << "a = " << ( int )a << "'\tb = " << ( int )b << std::endl;
if ( b > a ) std::cout << "b is greater than a, that is b is positive and a is negative\n";
}
The output is
a = fffffffc' 'b = 4
b is greater than a, that is b is positive and a is negative
Edit: Only now I have seen that definitions of the variables have to look as
char a = -4;
unsigned char b = a;
that is the minus in the definition of b ahould not be present.
Since an (unsigned) int is at least 16 bits wide, let's use that for instructional purposes:
In the first case: a = 0xfffc, and b = (unsigned int) (a) = 0xfffc
Following the arithmetic conversion rules, the comparison is evaluated as:
((unsigned int) b == (unsigned int) a) or (0xfffc == 0xfffc), which is (1)
In the 2nd case: a = 0xfc, and b = (unsigned char) ((int) a) or:
b = (unsigned char) (0xfffc) = 0xfc i.e., sign-extended to (int) and truncated
Since and int can represent the range of both the signed char and unsigned char types, the comparison is evaluated as: (zero-extended vs. sign-extended)
((int) b == (int) a) or (0x00fc == 0xfffc), which is (0).
Note: The C and C++ integer conversion rules behave the same way in these cases. Of course, I'm assuming that the char types are 8 bit, which is typical, but only the minimum required.
They both output 0 because unsigned values can get converted to signed values, not viceversa (like you said).

invalid operands of types int and double to binary 'operator%'

After compiling the program I am getting below error
invalid operands of types int and double to binary 'operator%' at line
"newnum1 = two % (double)10.0;"
Why is it so?
#include<iostream>
#include<math>
using namespace std;
int main()
{
int num;
double two = 1;
double newnum, newnum1;
newnum = newnum1 = 0;
for(num = 1; num <= 50; num++)
{
two = two * 2;
}
newnum1 = two % (double)10.0;
newnum = newnum + newnum1;
cout << two << "\n";
return 0;
}
Because % is only defined for integer types. That's the modulus operator.
5.6.2 of the standard:
The operands of * and / shall have arithmetic or enumeration type; the
operands of % shall have integral or enumeration type. [...]
As Oli pointed out, you can use fmod(). Don't forget to include math.h.
Because % only works with integer types. Perhaps you want to use fmod().
Yes. % operator is not defined for double type. Same is true for bitwise operators like "&,^,|,~,<<,>>" as well.