将无符号整数的高四位和低四位交换,帮忙debug一下
任务描述本关任务:编写完整的程序,从终端输入一个无符号短整数k,输出将k的高4位和低4位交换后的结果。例如,程序执行时:
输入:54321(对应二进制为11010100 00110001);
输出:5181 (对应二进制为00010100 00111101)。
相关知识
为了完成本关任务,你需要掌握:
标准输入输出格式;
移位操作;
有符号整数和无符号整数区别。
#include <stdio.h>
int main(){
/**********Begin**********/
unsigned short k,x;
scanf("%d",&k);
x=((k>>4)<<8)>>4|(k<<12)|(k>>12);
printf("%d",x);
/**********End**********/
return 0;
}
测试输入12,123,1234都能得到正确结果,输入12345时得到45107,正确结果是36915.
请求debug!在我的程序基础上修改,不要给出用其他方法的代码。 本帖最后由 shooan 于 2020-10-25 08:49 编辑
不知道这样改,符不符合你说的在我的代码基础上面修改
#include <stdio.h>
int main(){
/**********Begin**********/
unsigned short k,x;
scanf("%d",&k);
x = k;
char low4 = x & 0xF;
char high4 = x >> 12 & 0xF;
// 把高4个字节放到低4个字节
x &= 0xFFF0;
x |= high4;
// 把低4个字节放到高4个字节
x &= 0x0FFF;
x |= low4 << 12;
printf("%d",x);
/**********End**********/
return 0;
} 本帖最后由 xieglt 于 2020-10-25 09:13 编辑
帮你调试了一下,找到了原因。
看图。我用了3种方式去掉高4位和低4位,
第一种
x = k >> 4;
x <<= 8;
x >>= 4;
x = k >> 4编译成汇编代码是 sar cx,4 sar 是算术右移指令,它将保留最高位,所以会保留最高位的1
x <<= 8 汇编代码是shldx,8 shl 是逻辑左移指令
x >>= 4 汇编代码是shrax,4 shr 是逻辑右移右移指令,它不会保留最高位
最后得出 x = 48;
再看第二种,也就是你在程序里用的那种。
y = (k>>4)<<8)>>4
翻译成汇编代码是
sarecx,4
shlecx,8
sar ecx,4 右移全是用的算术右移sar,所以最高位被保留
最后得出 y 是 12336
第三种
z = k & 0X0FF0 这种应该是最靠普的。跟翻译过去的汇编指令无关
得出 z = 48
因此,得出结论,是因为编译器把 右移指令 翻译成指令sar,导致最高位保留造成的。 把中间那行改成
x = ((((k >> 4) << 8) >> 4) & 0x0FFF) | (k << 12) | (k >> 12);
就好了 xieglt 发表于 2020-10-25 09:11
帮你调试了一下,找到了原因。
看图。我用了3种方式去掉高4位和低4位,
第一种
真大佬 我明天再看下,然后选出最佳答案,谢谢各位 xieglt 发表于 2020-10-25 09:11
帮你调试了一下,找到了原因。
看图。我用了3种方式去掉高4位和低4位,
第一种
我总结以下,你看看对不对:
错因是:使用算数右移导致的结果偏差
所以解决方法是:修改代码,让编译器不使用算数右移,全部使用逻辑右移/左移 ?
所以& 0x0FFF的作用是什么,是强制转换为逻辑右移吗 本帖最后由 xieglt 于 2020-10-26 07:58 编辑
Danmoits 发表于 2020-10-26 07:24
我总结以下,你看看对不对:
错因是:使用算数右移导致的结果偏差
所以解决方法是:修改代码,让编译 ...
不是0x0FFF 是x = k & 0x0FF0
0X0FF0 这个十六进制数,每个数字代表4位,表示成二进制数就是 0000111111110000
高4位和低4位为0,就会将 k 的高4位和低4位清0
中间两个4位为F,就会将 k 的中间8位保留。
这是按位与运算,不是移位。
页:
[1]