我正在编写一个 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/