我正在编写一个C函数,该函数接受参数n并返回一个整数,该整数以n的位表示形式表示,其后是足够的0以填充数据类型(总共32位)。我的代码当前如下所示:

int upperBits(int n) {
    int retval = 0 - 1;
    int shift = 32 - n;
    retval = retval << shift;
    return retval;
}

当n = 0时,此代码失败,返回值-1由32 1而不是0表示。但是,当我用文字替换shift时:
int upperBits(int n) {
    int retval = 0 - 1;
    int shift = 32 - n;
    retval = retval << 32;
    return retval;
}

代码正常工作,返回0。当使用n = 0调用函数时,我使用了print语句来验证shift = 32,所以我不明白为什么它们的行为不同。是什么导致了这种差异,我该如何规避呢?

如果相关,则代码在Linux机器上运行,并使用gcc进行编译。我只需要对这些运算符使用直线代码:! ˜ & ˆ | + << >>
编辑:
我仍然不知道到底是什么问题,还是一个好的解决方案,但是这种解决方法很有效:
int upperBits(int n) {
        int retval = 0 - 1;
        int shift = 32 - n;
        int isnull = !(n);
        printf ("%x %x %x \n", retval, shift, n);
        retval = retval << (shift - isnull);
        retval = retval << isnull;
        printf ("%x %x %x \n", retval, shift, n);
        return retval;
}

最佳答案

您正在执行非法的左移。

向左移动负数会调用undefined behavior,向左移动大于或等于所讨论类型的位宽的数量也是如此。

C standard的6.5.7节中有关按位移位运算符的规定:



您可以通过使用无符号类型并检查移位的大小来纠正此问题:

uint32_t upperBits(int n) {
    uint32_t retval = 0xffffffff;
    if (n <= 0 || n > 32) {
        return 0;
    } else {
        int shift = 32 - n;
        retval = retval << shift;
        return retval;
    }
}

关于c - 文字常量和具有相同值的变量之间左移执行的差异,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52650933/

10-11 15:24