c - 文字常量与同值变量左移执行的差异

标签 c types bit-manipulation

我正在编写一个 C 函数,它接受参数 n 并返回一个 int,其位表示 n 个 1,后跟足够的 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。我使用 print 语句来验证当使用 n = 0 调用函数时,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 节关于按位移位运算符的状态:

3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2 E2 , reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2 E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

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

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/

相关文章:

c - 为什么我的 .c 文件无法识别我的头文件? 2 个错误,XCode

c - 当我们可以以相同的成本获得全局变量时,静态局部变量有什么用?

haskell - 如何在haskell中创建类的类型实例?

c - 使用位掩码提取十六进制的二进制表示会导致错误

c - C中Ascii Char转二进制的解释

c - 位运算剖析

C程序在打开端口失败前设置端口参数

java - 努力将 CRC-16 0x8408 从 C 反向转换为 Java

javascript - FlowJS 内联柯里化(Currying)函数类型与 Union

java - 生成随机二进制数据,例如 23ABFF