这是我的搭档想出的代码,但出于某种原因,我无法联系到他,问他应该如何工作。我已经经历过很多次了,似乎无法得到我应该得到的答案。
/**
* bitMask - Generate a mask consisting of all 1's
* lowbit and highbit
* Examples: bitMask(5,3) = 0x38
* Assume 0 <= lowbit <= 31, and 0 <= highbit <= 31
* If lowbit > highbit, then mask should be all 0's
* Legal ops: ! ~ & ^ | + << >>
*/
int bitMask(int highbit, int lowbit) {
int i = ~0;
return ~(i << highbit << 1) & (i << lowbit);
}发布于 2016-01-31 02:54:42
这个函数实际上是不正确的:对于highbit和lowbit的大值,它可能有实现特定的行为,甚至是未定义的行为。它应该使用并返回unsigned类型:
unsigned bitMask(int highbit, int lowbit) {
unsigned i = ~0U;
return ~(i << highbit << 1) & (i << lowbit);
}以下是几个步骤:
i = ~0U;将i设置为所有位1。i << highbit将这些位移到左边,在低阶位中插入highbit 0位。i << highbit << 1为多一个0位腾出了空间。我们不应该将这个表达式简化为i << (highbit + 1),因为如果highbit + 1变得更大或等于i类型中的位数,就定义了这样的位移位。~(i << highbit << 1)对此掩码进行了补充,创建了一个highbit + 1位的掩码,该掩码设置在低阶位置,0设置为较高的位。i << lowbit创建一个具有lowbit 0位和1在较高位置的掩码。~(i << highbit << 1) & (i << lowbit)计算这两个掩码的交集,结果从位号lowbit到位数highbit包含1位,将0中的位编号为最小有效位。例子:
bitMask(31, 0) -> 0xFFFFFFFF.bitMask(0, 0) -> 0x00000001.bitMask(31, 16) -> 0xFFFF0000.bitMask(15, 0) -> 0x0000FFFF.这种编号方法用于硬件规范。我个人更喜欢一种不同的方法,即指定要跳过的位数和要设置的位数,这更符合位字段规范:
unsigned bitSpec(int start, int len) {
return (~0U >> (32 - len)) << start;
}同样的例子:
bitSpec(0, 32) -> 0xFFFFFFFF.bitSpec(0, 1) -> 0x00000001.bitSpec(16, 16) -> 0xFFFF0000.bitSpec(0, 16) -> 0x0000FFFF.发布于 2016-01-31 02:49:48
在您的情况下,考虑到您的函数中包含的描述,该函数正在执行您似乎希望它做的事情。主要问题是您使用的是int而不是unsigned int。这将导致符号扩展的问题。(更不用说C中签署的轮班缺乏定义)。
向unsigned的简单转换将显示它正在按您的预期操作:
简短的例子:
#include <stdio.h>
#include <stdlib.h>
unsigned int bitMask (unsigned int highbit, unsigned int lowbit) {
unsigned int i = ~0;
return ~(i << highbit << 1) & (i << lowbit);
}
char *binstr (unsigned long n, unsigned char sz, unsigned char szs, char sep) {
static char s[128 + 1] = {0};
char *p = s + 128;
unsigned char i;
for (i = 0; i < sz; i++) {
p--;
if (i > 0 && szs > 0 && i % szs == 0)
*p-- = sep;
*p = (n >> i & 1) ? '1' : '0';
}
return p;
}
int main (int argc, char **argv) {
unsigned high = argc > 1 ? (unsigned)strtoul (argv[1], NULL, 10) : 5;
unsigned low = argc > 2 ? (unsigned)strtoul (argv[2], NULL, 10) : 3;
printf ("%s\n", binstr (bitMask (high, low), 32, 8, '-'));
return 0;
}输出
$ ./bin/bitmask
00000000-00000000-00000000-00111000
$ ./bin/bitmask 10 3
00000000-00000000-00000111-11111000
$ ./bin/bitmask 31 5
11111111-11111111-11111111-11100000
$ ./bin/bitmask 4 8
00000000-00000000-00000000-00000000https://stackoverflow.com/questions/35109714
复制相似问题