计算机系统学习笔记

本文介绍了C语言中处理有符号整数的逻辑右移和算术右移。逻辑右移用0填充左侧,算术右移则用符号位填充。对于无符号类型,所有移位都是逻辑的。若要对有符号数执行逻辑右移,可以将其转换为无符号类型,但可能会导致溢出。另一种方法是先算术右移,然后用与运算替换符号位为0。文章还给出了一个计算二进制中1的个数的C++实现例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

逻辑右移和算数右移

逻辑右移:右移后左边添加0

算术右移:右移后添加的位与原数的符号位相同

C语言中,对于移位操作执行的是逻辑左移算术右移

不过对于无符号类型,所有的移位操作都是逻辑的。

所以要相对一个有符号数执行逻辑右移,那么可以先将它强制类型转换为无符号类型。
如下

int mian()
{
    int n = 0xfffffffe;
    int m = (unsigned int)n >> 1;
    printf("0x%x\n", m);
}

这样右移有可能会产生溢出,变成负数。。。

但是这个计算机系统的datalab,需要把m也变成unsigned,这样所有的样例都通过了

emmmmm底下这一段我没看懂,但是也可以记录一下其他方法:

如果不允许强制类型转换,还要求把有符号数逻辑右移

因为c语言里的>>运算符默认是算术右移(算术右移符号位补位,逻辑右移0补位),所以可以先进行算术右移,再将补位的符号位(可能是0或1)换成0;

假设要逻辑右移n位,就需要将最高位的n位符号位全部替换成0,那么就可以利用左边n位为0,右边32-n位为1的二进制码与算术右移n位后的原码按位与&,便可得到逻辑右移n位后的目标数。

构造这个二进制码可以用:1 << 31得到100...,算术右移n位,得到1...10...0,共n+1位为1。再左移1位,即可得到 1...10...0,共n位为1,再将这个数取反即可。(当然也有其他构造方法)

/* 
 * logicalShift - shift x to the right by n, using a logical shift
 *   Can assume that 0 <= n <= 31
 *   Examples: logicalShift(0x87654321,4) = 0x08765432
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 3 
 */
int logicalShift(int x, int n) {
unsigned num1=(unsigned) x;
return num1>>n;
  //return ~((((1<<31)&x)>>n)<<1)&(x>>n);
}

今后继续整理算法并写出自己的理解和备注。

C++实现的:二进制中1的个数

1、 二进制中1的个数

int bitCount(int x) {
int res=0;
int var1=0x55|(0x55<<8);
int var2=0x33 |(0x33<<8);
int var3=0x0f |(0x0f<<8);
int var4=0xff|(0xff<<16);
int var5=0xff|(0xff<<8);
var1=var1|(var1<<16);
var2=var2|(var2<<16);
var3=var3|(var3<<16);

res= (x & var1) +((x>>1) & var1);
res= (res &var2) + ((res >>2) &var2);
res= (res &var3) + ((res >>4) &var3);
res= (res &var4) + ((res >>8) &var4);
res= (res &var5) + ((res >>16) &var5);
return res;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值