bitwise not and "auto casts"

J

J. Campbell

When the bitwise NOT operator, is placed in front of an integer
variable type (bool, char, short, int, long), the return value is a
signed int, regardless of the variable type. An example can be seen
in this code:

#include<iostream>

using namespace std;

int main(){
bool a = true;
bool b = !a;
cout << hex
<< a << endl // 1
<< b << endl // 0
<< ~a << endl // fffffffe
<< dec
<< ~a << endl // -2
<< hex
<< ~~a << endl // 1
<< ~~~a << endl; // fffffffe

cin.get();
return 0;
}

This doesn't see right...a bool that's been bit-notted *should* return
a single bit instead of returning 32-bits!! The same applies to a
bit-notted char...one would expect 8-bits in return.
Any comments
 
R

Ron Natalie

J. Campbell said:
When the bitwise NOT operator, is placed in front of an integer
variable type (bool, char, short, int, long), the return value is a
signed int, regardless of the variable type.

It is not. The type is the promoted type of the operand. It's not necessarily
a signed int. If you applied it to an unsigned, the result would be unsigned.

Bool however is promoted, just as it is for the rest of the mathematical operators.
Same thing happens with char, etc...

That's just the way C and C++ do their math.
 
J

J. Campbell

Ron Natalie said:
It is not. The type is the promoted type of the operand. It's not necessarily
a signed int. If you applied it to an unsigned, the result would be unsigned.

This actually is not true with my C++ compiler. In this example, the
signed int, -2 is returned for (not 1) for bool, char, and unsigned
char. If you print the hex, you will see that it's FFFFFFFE...clearly
(~variable) returns an unsigned int regardless of variable's type.

#include<iostream>
using namespace std;
int main(){
bool a = true;
unsigned char b = 1;
signed char c = 1;
cout << ~a << endl // -2
<< ~b << endl // -2
<< ~c << endl; // -2
cin.get();
return 0;
}

And in this example, bit notting a bool returns the same initial
value!!!

#include<iostream>
using namespace std;
int main(){
bool a = 1;
bool b = ~a;
if (a == b)
cout << "imagine that, b = not a, yet a == b!!!\n";
cin.get();
return 0;
}

Bool however is promoted, just as it is for the rest of the mathematical operators.
Same thing happens with char, etc...

That's just the way C and C++ do their math.

Yep...it just seems a little nonsensical that a notted bool can return
-2...when the only possible values for a bool are 1 and 0.

I do understand though...C++ takes the value and padds with leading
zeros then does the logic on that native-length int...and returns that
value. However, in this last example where b is assigned ~a, yet b
still evaluates equal to a...this seems like an example where the c++
treatment is a poor choice. Again, I understand why it evaluates this
way...bool a = 1, ~a == fffffffe, bool b = ~a, fffffffe != 0,
therefore b == true == 1. However this does not follow any kind of
natural boolean logic. if bool a = 1, then not a should evaluate to
0, with no if's ands or buts. I realize that this behavior can be had
using the logical not rather than the bitwise not...but I still don't
like it.

My old language had a similar problem. It boiled down to something
like this...

int a = 10. int b = not a. yet a and b both evaluate to true. This
is easy to understand because both a and b hold non-zero values,
therefore both true. But with a bool type, a and not a should never
both contain non-zero values!!!

Thanks for the response.
 
R

Ron Natalie

J. Campbell said:
This actually is not true with my C++ compiler. In this example, the
signed int, -2 is returned for (not 1) for bool, char, and unsigned
char. If you print the hex, you will see that it's FFFFFFFE...clearly
(~variable) returns an unsigned int regardless of variable's type.

No your tests are flawed. ostreams encoders are lousy things for determining
the TYPE of the object. Try typeid or using something that overloads over the
types you are trying to differentiate. The hex formatter always prints the number
as unsigned no matter what the input type is:

int i = -1
cout << hex << i << endl; // prints ffffffff

Second a math lesson: ~1 as a signed integer is -2, ~0 is -1 if you machine uses
2's complement math (as most do).

What happens when you apply ~ to a integral type is that the types are promoted
(as they are for the other math and bitwise operators). The following is straight
from 4.5 of the standard.

An rvalue of type char, signed char, unsigned char, short int, or unsigned short
int can be converted to an rvalue of type int if int can represent all the values of the source type; other-wise,
the source rvalue can be converted to an rvalue of type unsigned int.
An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true
becoming one.

Thus all the type conversion that you are observing happens prior to the ~ being applied.
The result of ~ is the promoted (from above) type of the argument.

None of your tests show otherwise.
 
S

Severin Ecker

hi!
If you print the hex, you will see that it's FFFFFFFE...clearly
(~variable) returns an unsigned int regardless of variable's type.
?? if the result of bit-inverting 1 is -2 then the result is not
unsigned!!?!
clearly if the MSB is 0 (positive int 2-complement) its inverted to 1
(negative)
and the other way round.
However this does not follow any kind of
natural boolean logic.
bitwise negation is not an operation of boolean logic, isn't it??? use !
instead,...

regards,
sev
 
J

J. Campbell

Severin Ecker said:
hi!

?? if the result of bit-inverting 1 is -2 then the result is not
unsigned!!?!

Yes...I meant signed.
clearly if the MSB is 0 (positive int 2-complement) its inverted to 1
(negative)
and the other way round.

I understood where the -2 came from...my point was just that, for a
1-bit integer number, it's not value should also be a 1-bit number.
bitwise negation is not an operation of boolean logic, isn't it??? use !
instead,...

indeed...this is what I've done
regards,
sev

Thanks for the reply.
 
J

J. Campbell

Ron Natalie said:
The following is straight
from 4.5 of the standard.

An rvalue of type char, signed char, unsigned char, short int, or unsigned short
int can be converted to an rvalue of type int if int can represent all the values of the source type; other-wise,
the source rvalue can be converted to an rvalue of type unsigned int.
An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true
becoming one.


Thanks Ron...this was my "discovery". I think this behavior is odd,
although I can understand and predict the output once it's understood.

In either case, you seemed to be insulted by my first reply to
you...no insult was intended.

I still think that the output from this code is not at all
intuitive...

#include<iostream>
using namespace std;
int main(){
bool a = 1;
bool b = ~a;
if (a == b)
cout << "imagine that, b = not a, yet a == b!!!\n";
cin.get();
return 0;
}

Output:
imagine that, b = not a, yet a == b!!!

I'd hazard a guess that many c++ programmers who consider theselves
competent would incorrectly predict the output of this program.

Joe (a not yet competent c++ programmer) ;-)
 
R

Ron Natalie

J. Campbell said:
I'd hazard a guess that many c++ programmers who consider theselves
competent would incorrectly predict the output of this program.

I don't know why. C and C++ has always promoted char's, why would bools
be any different. bools are never implmeneted as one bit storage anyhow because
they can't be smaller than char.
 
J

J. Campbell

Ron Natalie said:
I don't know why. C and C++ has always promoted char's, why would bools
be any different. bools are never implmeneted as one bit storage anyhow because
they can't be smaller than char.

Fair enough...that's why I signed off as a "non-competent c++
programmer". Cheers, and thanks for the pointer to the reference that
clarifies the (non)issue I raised.

Cheers.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top