Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why ~(true^true) is not true? Boolean operators (negation) works for `unsigned char`s, but not for bools? (C++)

I heard that often "everything" besides 0 is true. But now very strange things are happening to me... or I just think that I do it in correct way while I don't. Here's what is happening:

When I want to check if a is equivalent b, I can use NOT(a XOR b). When I checked it for unsigned char's, everything was ok, for example

unsigned char a = 5;
unsigned char b = 3;
unsigned char c = ~(a^b);

gave me c == 249:

a is: 00000101, which is 5.

b is: 00000011, which is 3.

~(a^b) is: 11111001, which is 249.

Now, let's try this with bool's.

cout << ~(true^true) << ~(true^false) << ~(false^true) << ~(false^false) << endl;
cout << ~(~(true^true)) << ~(~(true^false)) << ~(~(false^true)) << ~(~(false^false)) << endl;

if (~(true^true) == true)
    cout << "true";
else
    cout << "false";

This gives me in console:

-1-2-2-1
0110
false

while I expected the first line to be:

1001

After asking a friend, he advised me to try ! instead of ~ and see if it will work correctly. And (I think) it works correctly now. But I don't understand why. Shouldn't boolean negation work for bools?

like image 759
Kusavil Avatar asked May 18 '14 21:05

Kusavil


People also ask

What is negation operator in C?

The ! (logical negation) operator determines whether the operand evaluates to 0 (false) or nonzero (true). The expression yields the value 1 (true) if the operand evaluates to 0, and yields the value 0 (false) if the operand evaluates to a nonzero value.

What are true values in C?

Zero is used to represent false, and One is used to represent true. For interpretation, Zero is interpreted as false and anything non-zero is interpreted as true. To make life easier, C Programmers typically define the terms "true" and "false" to have values 1 and 0 respectively.

What is the purpose of the NOT Boolean operator?

The logical NOT ( ! ) operator (logical complement, negation) takes truth to falsity and vice versa. It is typically used with boolean (logical) values. When used with non-Boolean values, it returns false if its single operand can be converted to true ; otherwise, returns true .

Is 1 true or false in C?

Like in C, the integers 0 (false) and 1 (true—in fact any nonzero integer) are used.


2 Answers

You're misunderestimating the arithmetic conversions. When you say ~e for some expression e of integral type, the value is first promoted to at-least-int, and same for e1 ^ e2 (and for any arithmetic expressions, for that matter). So true ^ true first has its operands promoted to int, yielding 1 ^ 1, which is indeed 0, and thus you end up with ~0, which on your platform is -1.

You can vaguely make sense of your operation by converting the result back to bool:

std::cout << static_cast<bool>(~(true ^ true))

In your final problem, since you have an expression with the == operator where the two operands have different types, both operands are promoted to the common type, which is again int, and -1 is different from 1. Again, you can convert both operands to bool first to get the desired equality.


The meta lesson is that the built-in operators in C++ acting on integers really only operate on int and wider, but not on any of the shorter types (bool, char, short) (and similar considerations apply to passing integers through an ellipsis). While this may cause some confusion at times, it also simplifies the language rules a bit, I suppose. This is all part of the C heritage of C++.

like image 200
Kerrek SB Avatar answered Sep 28 '22 18:09

Kerrek SB


I heard that often "everything" besides 0 is true

It is valid for conditions as for example in the if statement (here and below I am citing the C++Standard)

The value of a condition that is an expression is the value of the expression, contextually converted to bool for statements other than switch

For example if you would write as

if (~(true^true) )
    cout << "true";
else
    cout << "false";

instead of your code snippet

if (~(true^true) == true)
    cout << "true";
else
    cout << "false";

or when the logical negation operator ! is used

9 The operand of the logical negation operator ! is contextually converted to bool (Clause 4); its value is true if the converted operand is false and false otherwise. The type of the result is bool

As for operator == then

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.

That is in case of

if (~(true^true) == true)

the usual arithmetic conversion is applied that is boolean value true is converted to integer value 1 and it is not equal to the expression of the left operanf because internal binary representation of the left operand differs from 1 as showed the output of your first code snippet..

like image 26
Vlad from Moscow Avatar answered Sep 28 '22 16:09

Vlad from Moscow