我只能使用这些运营商! 〜& ^ | +<< >>
这是我到目前为止的代码,但我无法弄清楚如何让它工作
int setEvenBitsToOne(){
int byte = 0x55;
int word = byte | byte << 8;
return word | word << 16;
}
答案 0 :(得分:1)
由于已知整数的大小,因此您可以对其进行硬编码。
int alternatingBits() {
switch( sizeof(int) ) {
case 2:
return 0x5555;
case 4:
return 0x55555555;
case 8:
return 0x5555555555555555;
default:
fprintf(stderr, "Unknown int size: %zu\n", sizeof(int));
exit(1);
}
}
sizeof(int)
是一个常量,因此编译器会将所有这些优化为常量。
但我认为这是一个有点琐碎的练习。首先,我们需要的是只改变偶数位。这可以通过使用1的位掩码,将其添加到数字,将掩码移动2个位置,然后再添加来完成。
// C doesn't have a way to represent literal binary numbers,
// so I'm using the Perl convention.
num += 0b000001
num += 0b000100
num += 0b010000
...and so on...
使用mask = mask << 2
移动位掩码。
我们还需要知道何时停止。由于我们正在推动整数大小的限制,我们不想做mask < INT_MAX
之类的事情,因为mask = mask << 2
可能会溢出。相反,我们可以一次迭代2个整数位。
int alternatingBits() {
/* Our number to start with */
int num = 0;
/* Our bitmask to add to the number */
int mask = 1;
/* The number of bits in an integer
(to avoid clutering the for loop) */
const int bits = sizeof(int) * 8;
/* Step through each even bit */
for( int i = 0; i < bits; i+=2 ) {
/* Add the mask */
num += mask;
/* Shift the 1 over two bits */
mask = mask << 2;
}
return num;
}
在这种情况下,@ Olaf在评论中提到了一个微妙的问题。当我们到达终点时,mask
将移位超过整数可以容纳的位数。即使我们当时没有使用它,它也会点击Undefined Behavior的龙,这是编译器做任何想做的事情的许可。
我们需要确保不会发生这种情况,这意味着我们必须编写自己的修改后的for
循环。
整数的高位也用于签名,所以我们应该使我们的位掩码成为无符号整数是安全的。
int alternatingBits() {
int num = 0;
unsigned int mask = 1;
const int bits = sizeof(int) * 8;
/* This does the same as a for loop, but lets us end before incrementing mask */
int i = 0;
while( 1 ) {
num += mask;
/* increment i and check if we're done before incrementing the mask */
i += 2;
if( i >= bits ) {
break;
}
mask = mask << 2;
}
return num;
}
现在mask
不会溢出,也不必担心签名位。