右移位将C中无符号整数的开头加1
我试图在C语言中移动一个16位地址来获得一个缓存模拟器的设置ID,但当我尝试向右移动时,我的数字上会多出一个1 我的电话号码是0010100011001。然后左移3位,得到0100011001000。到现在为止,一直都还不错。但是,我随后尝试右移6位,结果是00000 10100010011,而不是0000000 100010011。我所有的整数都是无符号的,当我尝试移位时,它只加一个1 我的尝试和转换代码如下。在我的示例中,tag_大小为3,b为6右移位将C中无符号整数的开头加1,c,bit-shift,C,Bit Shift,我试图在C语言中移动一个16位地址来获得一个缓存模拟器的设置ID,但当我尝试向右移动时,我的数字上会多出一个1 我的电话号码是0010100011001。然后左移3位,得到0100011001000。到现在为止,一直都还不错。但是,我随后尝试右移6位,结果是00000 10100010011,而不是0000000 100010011。我所有的整数都是无符号的,当我尝试移位时,它只加一个1 我的尝试和转换代码如下。在我的示例中,tag_大小为3,b为6 unsigned int temp
unsigned int temp = addr << tag_size;
unsigned int temp1 = temp >> b;
unsigned int setid = temp1 >> tag_size;
unsigned int temp=addr>b;
unsigned int setid=temp1>>标记大小;
16位int
s现在已经不常见了。您可以尝试将变量定义为short
,通常为16位。这完全取决于你使用的机器。如果要查找16位整数,也可以使用uint16
看起来问题可能是因为您使用的无符号int
实际上不是Christian Gibbons在评论中提到的16位。当您将0010100011001
左移3位时,您会得到1010001001001000
,最左边的1不会像您在16位整数中预期的那样被删除,然后当您再次右移时,您会得到不期望的添加1
您可以将代码更改为此,并且它应该按照您最初的预期工作:
uint16_t temp = addr << tag_size;
uint16_t temp1 = temp >> b;
uint16_t setid = temp1 >> tag_size;
uint16\u t temp=addr>b;
uint16\u t setid=temp1>>标记大小;
您应该使用掩码并选择您感兴趣的位;例如:
unsigned int temp = (addr << tag_size) & 0xffffu; // keep 16 low bits
unsigned int temp1 = temp >> b;
unsigned int setid = temp1 >> tag_size;
或
unsigned int temp=(addr>(b+标记大小);
这使得代码独立于
无符号int
大小,C保证至少为16位。请显示。通过输入和输出,您的系统实际上是否有16位int
s?看起来像“添加”1是移位超过第16位的同一个。这实际上是对可能发生的情况的一个很好的总结。关于使用精确宽度类型uint15\t
的好建议。虽然不是必需的,但如果您能胜任,一个简短的片段显示如何实现您的建议通常会增加您答案的价值。感谢您的改进我向OP的原始代码片段添加了一个建议更改。
unsigned int temp = addr & (0xffffu >> tag_size); // keep 16 low bits
unsigned int setid = temp >> b;
unsigned int temp = (addr << tag_size) & 0xffffu; // keep 16 low bits
unsigned int setid = temp >> (b + tag_size);