我们有时候会用到对一个32位的位集合来进行操作,比如:
1.设置一个unsigned int 的某一位.
2.得到给定范围内1的个数.
3.把指定的值放入一个整型数里面保存起来,比如RGBA(红,绿,蓝,透明度),这四个参数的取值范围都是0-255,一个unsigned char 类型即可保存一个参数,我们可以用一个unsigned int 类型来保存这四个值。
上面的这些情况就需要使用到位操作,下面就是一些具体的操作和实现:
下面这些函数需要一个enum:
enum Formats {
HALF_BYTE = 4,
BYTE = 8,
HALF_WORD = 16,
WORD = 32
};
这个函数可以在指定位置上面赋值,比如说我们可以把12这个数字放到uint32 current 的4-7位,那么current的位表现形式就为: Ox000000c0,再把15放到current的12-15位,那么current的表现形式就为:Ox0000f0c0.同样,我们也可以设置用8位,16位来保存我们需要的值。
/*
@parm target: 需要操作的数
@parm pos: 在第pos个位置上面进行操作
@parm format: 需要操作的位数(4,8,16,32)
@parm value: 需要设置的值
出错返回0,正确返回修改过后的值的副本
*/
uint32_t setValueTo(uint32_t target,
uint32_t pos, Formats format, uint32_t value) {
uint32_t tmp = pow(2, format) - 1;
uint32_t max = 32 / format;
if (pos < 0 || pos > max) {
return 0;
}
if (value > tmp) {
return 0;
}
target &= ~(tmp << pos * format);
return target |= (value << pos * format);
}
下面这个函数是上面函数的逆:得到指定位置的值:
/*
@parm target:需要操作的数
@parm pos:在第pos个位置上面进行操作
@parm format:需要操作的位数(4,8,16,32)
出错返回0,正确返回修改过后的值的副本
*/
uint32_t getValueAt(uint32_t target, uint32_t pos, Formats format) {
uint32_t max = 32 / format;
if (pos < 0 || pos > max) {
return 0;
}
uint32_t tmp = pow(2, format) - 1;
target &= (tmp << pos * format);
return (target >> pos * format);
}
下面这个函数可以用来把pos位置上面的位置为condition
/*
@parm target:需要操作的数
@parm pos:在第pos个位置上面进行操作
@parm condition:0 或者 1
出错返回0,正确返回修改过后的值的副本
*/
inline uint32_t switchBitCondition(uint32_t target, uint32_t pos, bool condition) {
if (pos < 0 || pos > 31) {
return 0;
}
if (condition) {
return target |= condition << pos;
}
uint32_t tmp = 0xffffffff - (1 << pos);
return target & tmp;
}
下面这个是得到pos位置上面的位(0 或 1) :
/*
@parm target:需要操作的数
@parm pos:在第pos个位置上面进行操作
出错返回-1,正确返回修改过后的值的副本
*/
inline int getBitCondition(uint32_t target, uint32_t pos) {
if (pos < 0 || pos > 31) {
return -1;
}
uint32_t tmp = 1;
target &= (tmp << pos);
return (target >> pos);
}
下面这个函数可以设置一段范围内的位:
/*
@parm target:需要操作的数
@parm begin: 需要设置位的开始索引
@parm end: 需要设置位的结束索引
出错返回0,正确返回修改过后的值的副本
*/
uint32_t setMultipleBitCondition(uint32_t target, uint32_t begin, uint32_t end, bool condition) {
if (begin > end
|| begin > 31
|| begin < 0
|| end > 31) {
return 0;
}
if (begin == end) {
return switchBitCondition(target, begin, condition);
}
uint32_t tmp = 1;
if (condition) {
for (uint32_t i = begin; i <= end; ++i) {
target |= (tmp << i);
}
} else {
for (uint32_t i = begin; i <= end; ++i) {
target &= (tmp << i);
}
}
return target;
}
下面这个函数得到一段范围里面位为1的个数:
/*
@parm target:需要操作的数
@parm begin: 需要搜索位的开始索引
@parm end: 需要搜索位的结束索引
返回修改过后的值的副本
*/
inline uint32_t countNumberOfOne(uint32_t target, uint32_t begin, uint32_t end) {
uint32_t cnt = 0;
for (uint32_t i = begin; i <= end; ++i) {
int flag = getBitCondition(target, i);
if (flag != -1 && flag != 0) {
cnt++;
}
}
return cnt;
}