Search code examples
ctype-conversionkernighan-and-ritchie

Type conversion: signed int to unsigned long in C


I'm currently up to chapter 2 in The C Programming Language (K&R) and reading about bitwise operations.

This is the example that sparked my curiosity:

x = x & ~077

Assuming a 16-bit word length and 32-bit long type, what I think would happen is 077 would first be converted to:

0000 0000 0011 1111 (16 bit signed int).

This would then be complemented to:

1111 1111 1100 0000.

My question is what would happen next for the different possible types of x? If x is a signed int the answer is trivial. But, if x is a signed long I'm assuming ~077 would become:

1111 1111 1111 1111 1111 1111 1100 0000

following 2s complement to preserve the sign. Is this correct?

Also, if x is an unsigned long will ~077 become:

0000 0000 0000 0000 1111 1111 1100 0000

Or, will ~077 be converted to a signed long first:

1111 1111 1111 1111 1111 1111 1100 0000

...after which it is converted to an unsigned long (no change to bits)?

Any help would help me clarify whether or not this operation will always set only the last 6 bits to zero.


Solution

  • Whatever data-type you choose, ~077 will set the rightmost 6 bits to 0 and all others to 1.

    Assuming 16-bit ints and 32-bit longs, there are 4 cases:

    Case 1

    unsigned int x = 077; // x = 0000 0000 0011 1111
    x = ~x; // x = 1111 1111 1100 0000
    unsigned long y = ~x; // y = 0000 0000 0000 0000 1111 1111 1100 0000
    

    Case 2

    unsigned int x = 077; // x = 0000 0000 0011 1111
    x = ~x; // x = 1111 1111 1100 0000
    long y = ~x; // y = 0000 0000 0000 0000 1111 1111 1100 0000
    

    Case 3

    int x = 077; // x = 0000 0000 0011 1111
    x = ~x; // x = 1111 1111 1100 0000
    unsigned long y = ~x; // y = 1111 1111 1111 1111 1111 1111 1100 0000
    

    Case 4

    int x = 077; // x = 0000 0000 0011 1111
    x = ~x; // x = 1111 1111 1100 0000
    long y = ~x; // y = 1111 1111 1111 1111 1111 1111 1100 0000
    

    See code here. This means the sign extension is done when the source is signed. When the source is unsigned, sign bit is not extended and the left bits are set to 0.