C语言中的位运算符相关笔试题

由于位运算具有运行效率高且不容易受到数据位数长短的影响,具有较好的移植性,同时,由于位运算都可以直接翻译为汇编代码,故代码的执行效率往往也比较高,故在嵌入式领域具有广泛的应用。

一、一些面试题

例一、

用一个表达式,判断一个数X是否为2的N次方,不用循环语句。

结果:!(X&(X-1))

例二、

取两个变量中较大数,不适用if,?,switch或其他判断语句。

结果:int max = (a+b+abs(a-b))/2

例三、

不使用中间变量交换a,b。

结果: 

 a = a^b;
 b = a^b;
 a = a^b;

例四、取0的反码。

错误写法:

unsigned int zero = 0;

unsigned int zerocomplement = 0Xff;

正确写法:

unsigned int zero = 0;

unsigned int zerocomplement = ~zero;

说明:需要考虑到在不同字长的机器上的移植性,错误写法默认16位,只能在16位机上运行,二使用位运算写的代码将不受字长限制,具有很好的移植性。

 

二、嵌入式系统中的典型应用。

应用一:将寄存器中的某一位置1或则清0,保持其他位不变。

int l_data;
void SetBit(int pos)//将某一位置位的操作
{
 if((pos >= 0) && (pos <= 31))
 {
  l_data |= BIT_MASK(pos);
 }
}
void ClrBit(int pos)//将某一位清0的操作
{
 if((pos >= 0) && (pos <= 31))
 {
  l_data &= ~BIT_MASK(pos);
 }
}

说明:

该操作的依据如下:

1.0|1 == 1,1|1 == 1,故无论0还是1同1执行|操作,结果为1;无论0还是1同0执行|操作,都将保持不变。

2.1&0 == 0,0&0 == 0,故无论0还是1同0执行&操作,结果为0;无论0还是1同1执行&操作,都将保持不变。

应用二、判断寄存器某一位为0还是1

bool is1(int pos)//判断某一位是否为1
{
 if((pos >= 0) && (pos <= 31))
 {
  if(l_data & (BIT_MASK(pos)) == 0x1)
  {
   return true;
  }
  else
  {
   return false;
  }
 }
}

应用三、将寄存器的某一位取反(1->0;0->1)

void ReverseBit(int pos)//将某一位取反
{
 if((pos >= 0) && (pos <= 31))
 {
  l_data ^= BIT_MASK(pos);
 }
}

说明:与0异或,保持不变;与1异或,取反。

应用四、保留2个数的不同部分,将它们合并为1个数

方法一:这两个数除了有效位之外,其他位均为0,可以将其先适当移位操作,然后在"|"运算。

例一:将temp中的低8位和t中的高4位组合成一个12位数

   unsigned short temp = 0x00AB;
   unsigned char t = 0xC0;
   temp = temp<<4;
   temp |= (t>>4);

例二:保留channel的底4位,将其作为result的高4位,result的低4位设置为0xC;

   channel = (channel<<4) | 0x0C;

方法二:如果这2个数除了有效位之外,其他位需要保留为1,方法是先与适当的数"|",之后2个数"&"

例一:保留temp的高4位和line的底4位,并将其组合成result。由于line的其他位全位1,所以必须先将temp的其他位全部设置为1,之后2个数"&"即可。

   unsigned char result;
   unsigned char temp = 0xAB;
   unsigned char line = 0xFE;
   temp |= 0x0F;
   result = temp&line;

应用五、将一个16位数的高低8位分别拆成2个8位数,方法是通过多字节数赋给少字节数,多字节数高位字节部分将被自动截取的原理。

   unsigned short temp = 0xCDAB;
   unsigned char fir;
   unsigned char sec;
   fir = temp>>8;
   sec = temp;

应用六、如果CPU没有来算数移位操作,如何用逻辑移位操作实现。

例如:line = 0xFE,如何实现其的左移操作后,右边补入的是1而不是默认的0。

   line = (line<<1)|0x01;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值