我有一个非常简单的代码,其中逻辑移位以奇怪的方式处理〜0值
据我所知,它与有符号/无符号数据类型有关
A.x = dec(x)
我希望0111111,而不是1111111。 我也尝试过,没有成功
#include <stdio.h>
void printfbits(int x) {
for (int i=7; i>=0;i--) {
printf("%d", x>>i & 1);
}
printf("\n");
}
int main() {
printfbits(~0>>1);
}
答案 0 :(得分:7)
在大多数平台上,int
的长度为32位或64位。因此,您向右移动了8位以上,从而使您启用了8位以上:
11...11111111 >> 1
成为:
11...11111111 // if sign extension happens
01...11111111 // if not
如您所见,无论是否进行符号扩展,您都将看到所有1
,因为您只打印了低8位。
答案 1 :(得分:4)
负号的右移是定义的实现。对于gcc,移入1,否则移入0。
使用强制转换时您处在正确的轨道上,但这无济于事,因为该函数仍然需要int
。您需要将函数更改为采用unsigned char
,并且必须屏蔽掉除最低字节以外的所有字节,然后才能执行函数调用中的移位。
#include <stdio.h>
void printfbits(unsigned char x) {
for (int i=7; i>=0;i--) {
printf("%d", x>>i & 1);
}
printf("\n");
}
int main() {
printfbits((~0u & 0xff)>>1);
}
此外,请注意在常量0上使用U
后缀。这使常量具有unsigned int
类型。
答案 2 :(得分:1)
~0
中的否定将与类型int
一起发生。
但是,即使您执行~(unsigned char)0
,由于隐式提升,使用int类型仍然会发生这种情况。
因此,您将在左侧获得更多的1位(int通常为32位大(必须至少为16位))。
您可以通过将否定结果强制转换为uint8_t
来剥离它们。
我还建议对unsigned
(而不是0
(0
u)进行位操作,因为它们的语义更好地标准化了。
#include <stdio.h>
#include <stdint.h>
void printfbits(int x) {
for (int i=7; i>=0;i--) {
printf("%d", x>>i & 1);
}
printf("\n");
}
int main() {
printfbits( (uint8_t)~0u >>1 ); //prints 01111111
}
答案 3 :(得分:0)