用位运算实现有符号16bit数据clamp

在处理16 bit数据时,时常要将其他类型数据固定在16bit。

通常来说,在C语言中用一个if或者三目运算符就可以完成这个功能:

#define Limit16(a) ((a) > 0x7FFF ? 0x7FFF : ((a) < -0x8000 ? -0x8000 : (a)))

 

用位运算也可以巧妙实现此功能:

short clamp16(int sample)
{
    if ((sample >> 15) ^ (sample >> 31)) {
        sample = 0x7FFF ^ (sample >> 31);   
    }
    return sample;
}

 

代码流程说明如下:
  • 0 < sample <= 0x7FFF:
     sample >> 15 为 0;
     sample >> 31 为 0;
     异或后为0,跳过if,return sample;
  • sample > 0x7FFF:
     sample >> 15 为 1;
     这里的int假定为32位,sample >> 31 为 0;
     进入if后,sample = 0x7FFF ^ 0 = 0x7FFF;
  • -0x8000 <= sample < 0:
     sample >> 15 为 0xFFFFFFFF(高位为1,右移补1),负数是以补码的形式存在,大于-0x8000的数,高16位为1;
     sample >> 31 为 0xFFFFFFFF,异或为0;
     直接return
 
  • sample < -0x8000:
     sample >> 15 为0xFFFFxxxx低16位不确定,不全为1,sample >> 31 为 0xFFFFFFFF;
     异或后不为0,进入if;
     sample = 0x7FFF ^ 0xFFFFFFFF = 0xFFFF8000; 0xFFFF8000为其补码,值为-0x8000;
 
虽然这样的代码可能不便于阅读,不过作为一种位运算技巧,了解一下还是挺不错的。
posted @ 2017-06-01 14:21  Kelvin&  阅读(795)  评论(0编辑  收藏  举报