1

1st Semester Student here. I'm confused about the differences between the bitand (&) and the logical and (&&), and the same with the bitor (|), the logical or (||), and the Xor (^). Specifically, I've a bit of code that I thought required the || or && to function, but.. apparently not? Here's the code in question:

cout << "Please enter your biological sex (M or F): " << endl;
cin >> sex;

//Repetition Structure
while (toupper(sex) != 'M' && 'F')
{
    cout << "Invalid entry. Please enter your biological sex (M or F): " << endl;
    cin >> sex;
} //end while

I tried using || at first, but it gave me the "invalid entry" reply no matter how I answered it. I looked around on the forums, found that && would be better and tried using it. It worked - at first. Then, for no apparent reason, it stopped taking 'F' as an answer (the code wasn't changed).

To correct this, I tried using Xor (^) which failed, and then bitand (&, instead of &&), which apparently made it function correctly once more. But, I've seen warnings that you can still get the right answers using either & or &&, but one does not equal the other and could cause problems later. This is why I need clarification (also, it's just good stuff to know).

UPDATE: Since this was tagged as a duplicate, I'll clarify my intent: I want to know more about & and &&, why you use one and not the other, as well as the same info for ^, | and ||. The tagged thread has examples of using one versus another, but they don't explain the details of the operations themselves. As I'm struggling with understanding the very nature of the operations themselves, those explanations are crucial; examples alone won't clarify my understanding.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
CVHansen
  • 59
  • 8
  • 3
    `toupper(sex) != 'M' && toupper(sex) != 'F'` – apple apple Dec 06 '16 at 11:09
  • ` && 'F'` is always true – Raindrop7 Dec 06 '16 at 11:12
  • Any *non-zero* integral value is considered **true** in `C++`. Characters (`char`) are basically integers so all characters (except the null char `'\0'`) evaluate to **true**. So when you go `&& 'F' you are saying `&& true`. – Galik Dec 06 '16 at 11:21
  • OT: If `sex` is of type `char`, you need a cast to protect yourself against potential UB: https://stackoverflow.com/questions/21805674/do-i-need-to-cast-to-unsigned-char-before-calling-toupper – Baum mit Augen Dec 06 '16 at 11:23
  • 1
    @StoryTeller Thank you for the link. I read that forum, but it didn't clarify the matter for me. Good examples listed, but most of the talk was above my head (experienced programmers discussing shortcuts I've never even heard of, giving examples of things I haven't used yet as a Student, etc.). – CVHansen Dec 06 '16 at 11:50
  • apple apple, Raindrop and Galik gave you the answer. toupper(sex) applies only to the first != operator, not to the second. In terms of bitwise operators look at a [tutorial](https://www.tutorialspoint.com/cprogramming/c_bitwise_operators.htm). – MikeJRamsey56 Dec 06 '16 at 13:06

2 Answers2

5

This isn't something you use bit operators for. You want to compare input string with a desired 'M' or 'F' so all you have to do is:

while (toupper(sex) != 'M' && toupper(sex) != 'F') {...

In your code you were missing the second toupper(sex) != part. You need to look at this statement as two requirements that have to be met in order for while to continue.
First one is: toupper(sex) != 'M'
Second on: toupper(sex) != 'F'
The reason why a &&(logical and) should be between those two is because you want the while loop to run if sex isn't M and at the same time it isn't F.

Operators like & and | are for comparing bits of a variable. For example if you want to use bit flags you set each of your flag to one bit and compare the resulting flag combination with &.

EDIT: So for bit flags, they compare the value you give them bit by bit. So what you do for bit flags is you can define them as powers of 2 (1, 2, 4, 8...) which each represents on position in binary (00000001, 00000010, 00000100, 00001000 ...). So for example when you have flags:

a = 1;
b = 2;
c = 4;

You can set them with ``| to your set of flags:

setFlags = setFlags | a | c;

This will compare the setFlags bit by bit with a and c.

 00000000
|00000001 // a
|00000100 // c
=00000101 // result

So the | operator checks all the bits of the same position and if one of them is true, the result will be true just like logical OR. Now to read them you use & like this:

if (setFlags & a)

which does:

 00000101 // setFlags
&00000001 // a
=00000001 // result

this leaves only bits where they both are true (just like logical AND), therefore you can get true if the setFlags contains that flag.

 00000101 // setFlags
&00000010 // b
=00000000 // result

in this case there are no bits set to true on same position so the result tells you that b isn't set in setFlags.

quamrana
  • 37,849
  • 12
  • 53
  • 71
Maroš Beťko
  • 2,181
  • 2
  • 16
  • 42
  • Could you explain what bit flags are? That isn't a term covered in my beginner's c++ class this semester. Thank you! – CVHansen Dec 06 '16 at 11:52
0
 while (toupper(sex) != 'M' && 'F') is evaluated as:

 while(true  && (bool)'F'): while(true  && true)  // or
 while(false && (bool)'F'): while(false && true)

because if you sex is assigned 'm' or 'M' then the condition is true and you used logical and && on a non-zero value 'f' the result is always true.

it is like: if( (bool)5 ) which is true because the bool values of any non-zero value is always true.

to correct you example:

while (toupper(sex) != 'M' && toupper(sex) != 'F')

logical operators like logical and &&, logical or ||,... return bool values true or false; 1 or 0 they evaluate expressions.

bitwise operators like bitwise and &, bitwise or |... return any value, the y work on bits:

unsigned char uc1 = 13; // 0x01    00001101
unsigned char uc2 = 11; // 0x03    00001011

unsigned char uc3 = (uc1 & uc2);// 00001001

as you can see 1 & 1 = 1, 0 & 1 = 0, 1 & 0 = 0, 1 & 1 = 1, 0 & 0 = 0... the result us 00001001 which is in decimal 9

Raindrop7
  • 3,889
  • 3
  • 16
  • 27