繁体   English   中英

按位运算和转移问题

[英]Bitwise operations and shifts problems

我正在测试函数fitsBits(int x,int n),我发现有一个条件不适合这个函数,有什么问题?

/*
* fitsBits - return 1 if x can be represented as an 
*  n-bit, two's complement integer.
*   1 <= n <= 32
*   Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
*   Legal ops: ! ~ & ^ | + << >>
*   Max ops: 15
*   Rating: 2
*/
int fitsBits(int x, int n) {
   int r, c;
   c = 33 + ~n;
   r = !(((x << c)>>c)^x);
   return r;
}

似乎它给出了错误的答案

fitsBits(0x80000000, 0x20);

它给了我1,但实际上应该是0 ......我怎么能解决它? 谢谢!

对于签名类型,未定义导致溢出的左移。 因此,编译器可以将(x<<c)>>c简化为x ,并且整个函数减少到return 1;

可能你想使用无符号类型。

代码中未定义行为的第二个原因是c可能大于或等于int的宽度。 超过整数类型宽度的移位是未定义的行为。

fitsBits(0x80000000, 0x20);

这个函数返回1 ,因为函数的第一个参数是int ,它实际上是(实际上是这些天)32位有符号整数。 签名32位整数可以表示的最大值是0x7FFFFFFF,小于您传入的值。因此,您的值被截断并变为-0x80000000 ,这是32位整数可以表示的值。 因此,您的函数返回1 (是的,我的第一个参数是可以使用0x20 = 32位表示的东西)。

如果您希望函数正确地将数字0x80000000分类为无法使用32位表示的内容,则需要更改函数的第一个参数的类型。 一个选项可能是使用unsigned int ,但是从您的问题定义中看起来您需要正确处理负数,因此您的剩余选项是long long int ,可以保存-0x80000000000000000x7FFFFFFFFFFFFFFF之间的数字。

你需要做更多的调整:你需要通过使用LL后缀明确指定你的常量类型为long long ,现在你需要移动64 - c ,而不是32 - c

#include <stdio.h>

int fitsBits(long long x, int n) {
   long long r;
   int c;
   c = 65 + ~n;
   r = !(((x << c)>>c)^x);
   return r;
}

int main() {
    printf("%d\n", fitsBits(0x80000000LL, 0x20));
    return 0;
}

链接到IDEONE: http ://ideone.com/G8I3kZ

r = (((x << c)>>c)^x); //This will give you 0, meaning r = 0;

要么

r = !((x << c)>>c);

您的功能可以简化为

int fitsBits(int x) {

    int r, c; 
    c = 33; 
    r = (((x << c)>>c)^x);

    return r;
}

请注意,当NOT( ! )被带来时,你要求r相反

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM