سؤال

I was reading about i/o systems in C++ when I came across an example with bitwise operators, I mistakenly put logical operators when trying it out, and the result was different. I cannot understand why this is so,

void main(){
    ios::fmtflags f;
    f = cout.flags();

    if(f & ios::showpos)
        cout << "showpos is set for cout. \n";
    else 
        cout << "showpos is cleared for cout. \n";

    cout << "setting showpos for cout. \n";
    cout.setf(ios::showpos);

    f = cout.flags();
    if(f & ios::showpos)
        cout << "showpos is set for cout. \n";
    else 
        cout << "showpos is cleared for cout. \n";

    cout << "clearing showpos for cout. \n";
    cout.unsetf(ios::showpos);

    f = cout.flags();
    if(f & ios::showpos)
        cout << "showpos is set for cout. \n";
    else 
    cout << "showpos is cleared for cout. \n";

    cout << "\n";

    f = cout.flags();

    if(f && ios::showpos)
        cout << "showpos is set for cout. \n";
    else 
        cout << "showpos is cleared for cout. \n";

    cout << "setting showpos for cout. \n";
    cout.setf(ios::showpos);

    f = cout.flags();
    if(f && ios::showpos)
        cout << "showpos is set for cout. \n";
    else 
        cout << "showpos is cleared for cout. \n";

    cout << "clearing showpos for cout. \n";
    cout.unsetf(ios::showpos);

    f = cout.flags();
    if(f && ios::showpos)
        cout << "showpos is set for cout. \n";
    else 
    cout << "showpos is cleared for cout. \n";
}

Here are the results,

showpos is cleared for cout.
setting showpos for cout.
showpos is set for cout.
clearing showpos for cout.
showpos is cleared for cout.

showpos is set for cout.
setting showpos for cout.
showpos is set for cout.
clearing showpos for cout.
showpos is set for cout.
Press any key to continue . . .

The correct result is the one with the bit-wise operator, but why is the logical operator wrong? How do you know which operator to use when programming?

هل كانت مفيدة؟

المحلول 2

Let assume that you have two values

int first  = 0x1;
int second = 0x2;

or using binary literals

int first  = 0b01;
int second = 0b10;

As each of them is not equal to zero then expression

first && second

will be true. Non-zero values of scalar types are implicitly converted to true in logical expressions.

On the other hand if you will use expression

first & second

in some condition then it always will be equal to false because there is no common bit for the both numbers that is set. In the first number the first bit is set but in the second number it is equal to zero. In the second number the second bit is set but in the frist number it is rqual to zero.

So

0b01
&
0b10
====
0b00

As the result is equal to zero then it will be converted to false in logical expressions.

نصائح أخرى

In this case, f is being used as a bit array. You can think of any primitive type as a bit array - for example, if your int is 32-bit, then it's like having a bit array of size 32. How do you write 1 to the fourth bit?

f = f | 8

Because 8's binary representation is 1000 (i.e. fourth bit). How do you write 0 to the fourth bit?

f = f & ~8

This is because ~8 will create such a bit array where only the fourth bit is 0. Now, to get the value of the fourth bit, you'll do:

f & 8

This last operation will return 8 if the fourth bit is 1, and 0 if the fourth bit is 0.

In boolean terms however, anything other than 0 is true - and only 0 is false. This means that if you do f & 8 and cast it to boolean, you'll get true only if the fourth bit was 1, and false only if the fourth bit was 0. However, if you do f && 8 the result will be true as long as f is non-zero - because 8 cast to boolean is true.

When dealing with flags, you usually want bit-wise. The reason here is that you're testing a single bit (or sometimes multiple bits). The ios::showpos value has all bits zero except for one.

When you do a bit-wise & on your flags, the effect is to isolate a specific value. If the result is non-zero, the flag is set. If zero, the flag is not set.

When you use logical &&, you're doing something different. You're testing whether both sides of the operator are true (non-zero). If they are, then the result is also true. Otherwise it is false.

So, when you do if(f && ios::showpos), the result is true because both f and ios::showpos are non-zero values.

Madz, the two results may differ, because both the operators are totally different...

consider this,

int i = 10;
int j = 2;

if (10 & 4)   // will evaluate false

and

if (10 && 4)  // will evaluate true..

Explanation: bitwise and operator calculates bits.

10 = 1010 in binary
4 = 0100 in binary

hence 10 & 4 results 0, which is equivalent to false.

and in c or c++, any thing other than 0 is true, remember,
hence 10 && 4, (i.e true && true) evaluates to true...

Hope that solves your issue.. :)

look Madz its the problem with C++, let me explain c++ treats all integers a true value except 0. so when you are trying two different expressions one with "&" and other with "&&", c++ evaluates the expression true. for eg.

int i=5;
int j = i>1 && i<10;  //j gets 1 here, being treated as true
int k = i>1 & i<10;   // here k also gets 1, because 1 AND 1 = 1

or you can think of its as

TRUE AND TRUE ---> TRUE

TRUE AND FALSE ---> FALSE

i think you get it.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top