Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 356
SpruceMoose Avatar asked Dec 03 '13 07:12

SpruceMoose


2 Answers

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.

like image 103
Sufian Latif Avatar answered Oct 04 '22 02:10

Sufian Latif


 x = x & ~077    //~077=11111111111111111111111111000000(not in every case)

~077 is a constant evaluated at the complie time so its value will be casted according to the value of x at the compile time so the AND operation will always yield to last 6 bits of x to 0 and the remaining bits will remain whatever they were before the AND operation. Like

//let x=256472--> Binary--> 0000 0000 0000 0011 1110 1001 1101 1000
 x = x & ~077;
// now x = 0000 0000 0000 0011 1110 1001 1100 0000 Decimal--> 256448

So the last 6 bits are changed to 0 irrespective of the data type during the compile time remaining bits remain same. And in knr it is written there The portable form involves no extra cost, since ~077 is a constant expression that can be evaluated at compile time.

like image 21
APan Avatar answered Oct 04 '22 02:10

APan