Rya*_*sen 2 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;
}
Run Code Online (Sandbox Code Playgroud)
当n = 0时,此代码失败,返回值为-1,由32 1表示,而不是0.但是,我将shift替换为文字:
int upperBits(int n) {
int retval = 0 - 1;
int shift = 32 - n;
retval = retval << 32;
return retval;
}
Run Code Online (Sandbox Code Playgroud)
代码正常工作,返回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;
}
Run Code Online (Sandbox Code Playgroud)
你正在进行非法的左移.
左移一个负数会调用未定义的行为,就像移动大于或等于所讨论类型的位宽的量一样.
关于按位移位运算符的C标准的第6.5.7节规定:
3对每个操作数执行整数提升.结果的类型是提升的左操作数的类型. 如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为未定义.
4 E1 << E2的结果是E1左移E2位位置; 腾出的位用零填充.如果E1具有无符号类型,则结果的值为E1×2 E2,比结果类型中可表示的最大值减少一个模数. 如果E1具有带符号类型和非负值,并且E1×2 E2可在结果类型中表示,那么这就是结果值; 否则,行为未定义.
您可以使用无符号类型并通过检查班次的大小来更正此问题:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
59 次 |
最近记录: |