负数:如何将signed int中的符号位更改为0?

Mik*_*ike 2 c bit-manipulation

我在想这个世界是有效的,但事实并非如此:

int a = -500;
a = a << 1;
a = (unsigned int)a >> 1;
//printf("%d",a) gives me "2147483148"
Run Code Online (Sandbox Code Playgroud)

我的想法是左移会移除最左边的符号位,所以右移它作为无符号整数将保证它是一个逻辑移位而不是算术.为什么这不正确?

也:

int a = -500;
a = a << 1;
//printf("%d",a) gives me "-1000"
Run Code Online (Sandbox Code Playgroud)

use*_*500 7

TL; DR:最简单的方法是使用abs函数<stdlib.h>.答案的其余部分涉及在计算机上表示负数.

负整数(几乎总是)以2的补码形式表示.(见下面的注释)

获得数字否定的方法是:

  1. 取整数的二进制表示(包括数据类型的前导零,除了将用作符号位的MSB).
  2. 取上述数字的1的补码.
  3. 添加1到1的补码.
  4. 前缀符号位.

以身500作为例,

  1. 采取的二进制表示500:_000 0001 1111 0100(_为符号位的占位符).
  2. 取1的补码/倒数: _111 1110 0000 1011
  3. 添加1到1的补码:_111 1110 0000 1011 + 1 = _111 1110 0000 1100.2147483148当您将符号位替换为零时,这与您获得的相同.
  4. 前缀0显示正数和1负数:1111 1110 0000 1100.(这与2147483148上面不同.你得到上述价值的原因是因为你获得了MSB).

反转标志是一个类似的过程.如果您使用16位或32位数字导致您看到的大值,那么您将得到领先的数字.在每种情况下LSB应该相同.

注意:有些机器具有1的补码表示,但它们是少数.2的补码通常是首选,因为0具有相同的表示,即,-0并且0在2的补码表示法中表示为全零.