Pregunta

I'm doing a pretty trivial computer science homework revolving around bitwise operators in C, but I've run into an issue that I have no clue why it's happening. Here is the code I'm running.

    #include <stdio.h>

int main(int argc, char *argv[]){
    int bitPattern1 = 0x10011001;
    int bitPattern2 = 0x01100110;
    int bitPattern3 = 0xFFFFFFFF;
    int bitPattern4 = 0x00000000;

    /* pair 1 */
    printf("bitPattern1 &  bitPattern2 = %x\n", bitPattern1 &  bitPattern2);
    printf("bitPattern1 && bitPattern2 = %x\n", bitPattern1 && bitPattern2);

    /* pair 2 */
    printf("bitPattern1 |  bitPattern2 = %x\n", bitPattern1 |  bitPattern2);
    printf("bitPattern1 || bitPattern2 = %x\n", bitPattern1 || bitPattern2);

    /* pair 3 */
    printf("bitPattern1 &  bitPattern3 = %x\n", bitPattern1 &  bitPattern3);
    printf("bitPattern1 && bitPattern3 = %x\n", bitPattern1 && bitPattern3);

    /* pair 4 */
    printf("bitPattern1 |  bitPattern3 = %x\n", bitPattern1 |  bitPattern3);
    printf("bitPattern1 || bitPattern3 = %x\n", bitPattern1 || bitPattern3);

    /* pair 5 */
    printf("bitPattern2 &  bitPattern4 = %x\n", bitPattern2 &  bitPattern4);
    printf("bitPattern2 && bitPattern4 = %x\n", bitPattern2 && bitPattern4);

    /* pair 6 */
    printf("bitPattern2 |  bitPattern4 = %x\n", bitPattern2 |  bitPattern4);
    printf("bitPattern2 || bitPattern4 = %x\n", bitPattern2 || bitPattern4);

    return 0;
} 

The problem happens with the first part of pair 4 which returns with the following result:

bitPattern1 |  bitPattern3 = ffffffff
bitPattern1 || bitPattern3 = 1

Why is the bitwise operator returning the "f"s I've looked up the documentation and I though that the OR operator returns a 1 or a zero it seems that that example should return "11111111". Is it something to do with the hexadecimal numbers? I haven't been able to find anything on google.

¿Fue útil?

Solución

Firstly, the input of your OR is FFFFFFFF in hex notation, which means that in binary (bitwise) terms it is 11111111111111111111111111111111. I.e. it is a lot more 1s than you quoted (32 bits, to be exact).

Secondly, the bitwise OR in question should indeed return 1111111...1 in binary notation. And that is exactly what it returns. But when you print the result in hex notation, you get FFFFFFFF. You explicitly requested hex notation by using x format specifier in printf.

Unfortunately, printf has no format specifier for producing binary notation. However, converting hex to binary is a trivial task, since it is a straightforward replacement of each hex digit with four binary digits. F stands for 1111, so as you can see, in bitwise terms your OR did indeed produce 11111111111111111111111111111111, as it should.

Otros consejos

Bitwise operators operate on all bits in the arguments, matching each bit with its counterpart in performing the operation. Since you assigned bitPattern3 = 0xFFFFFFFF all 32 bits are on, so bitwise OR-ing it (|) with anything would leave all bits toggled on.

Logical OR (||) would treat the arguments as true/false, and perform a simple OR operation on them, returning a true/false value

The OR and AND operators come in two flavors, logical (|| and &&) and arithmetic (| and &).

Logical OR and AND will return a bool result. These are your "English-like" conjunctions.

Arithmetic OR and AND work on the bit-level, doing the conjunction on each respective bit.

In the former case of logical comparisons (|| and &&), you will typically be comparing booleans. For example:

bool shouldUpdate = (hasNetworkConnection && isNewerVersionAvailable);
bool isDifferentLocation = (location.X != this.X || location.Y != this.Y);

For the latter case of arithmetic comparisons, these are typically done with enum values that are Flags, like so:

[Flags]
enum AccessModeFlags
{
  None = 0x0,
  Read = 0x1,
  Write = 0x2,
  ReadWrite = Read | Write
}

In this case, ReadWrite is 0x3 because it is a bitwise OR of 0000 0001 and 0000 0010, resulting in 0000 0011.

This is tangential to your issue, but the lines:

int bitPattern1 = 0x10011001;
int bitPattern3 = 0xFFFFFFFF;

cause implementation-defined behaviour or raise an implementation-defined signal, because the values 0x10011001 and 0xFFFFFFFF are out of range of "int", assuming you are using 32-bit ints.

It's important to understand that when you write these lines, you are not explicitly storing that bit pattern in the variable. You're storing the VALUE 4294967295 in the variable, and the compiler gets to choose what bit pattern it uses to store that value. It can do anything it likes so long as when you access the value you get back what you put in -- although for reasons of simplicity, computers these days almost all use two's complement representation.

In this case the max value for an int is 2147483647, so your assignment is out of range . But GCC has decided to handle this by guessing that you meant to assign whatever value which leads to the two's complement representation FFFFFFFF. Other compilers could abort the program at this point and still comply with the C standard.

Also you pass "int"s to %x, causing undefined behaviour if the int is negative. "%x" expects an "unsigned int".

You can avoid these issues by changing all your "int" to "unsigned int".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top