鱼C论坛

 找回密码
 立即注册
查看: 3395|回复: 7

[已解决]将无符号整数的高四位和低四位交换,帮忙debug一下

[复制链接]
发表于 2020-10-24 18:33:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
任务描述
本关任务:编写完整的程序,从终端输入一个无符号短整数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!在我的程序基础上修改,不要给出用其他方法的代码。
最佳答案
2020-10-25 09:11:48
本帖最后由 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     汇编代码是  shl  dx,8                 shl 是逻辑左移指令
x >>= 4     汇编代码是  shr  ax,4                 shr 是逻辑右移右移指令,它不会保留最高位
最后得出 x = 48;

再看第二种,也就是你在程序里用的那种。
y = (k>>4)<<8)>>4
翻译成汇编代码是
sar  ecx,4
shl  ecx,8
sar ecx,4                                              右移全是用的算术右移sar,所以最高位被保留
最后得出 y 是 12336

第三种
z = k & 0X0FF0                                    这种应该是最靠普的。跟翻译过去的汇编指令无关
得出 z = 48

因此,得出结论,是因为编译器把 右移指令 翻译成指令  sar  ,导致最高位保留造成的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-10-25 08:47:16 | 显示全部楼层
本帖最后由 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;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-10-25 09:11:48 | 显示全部楼层    本楼为最佳答案   
本帖最后由 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     汇编代码是  shl  dx,8                 shl 是逻辑左移指令
x >>= 4     汇编代码是  shr  ax,4                 shr 是逻辑右移右移指令,它不会保留最高位
最后得出 x = 48;

再看第二种,也就是你在程序里用的那种。
y = (k>>4)<<8)>>4
翻译成汇编代码是
sar  ecx,4
shl  ecx,8
sar ecx,4                                              右移全是用的算术右移sar,所以最高位被保留
最后得出 y 是 12336

第三种
z = k & 0X0FF0                                    这种应该是最靠普的。跟翻译过去的汇编指令无关
得出 z = 48

因此,得出结论,是因为编译器把 右移指令 翻译成指令  sar  ,导致最高位保留造成的。
222.JPG
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

发表于 2020-10-25 09:25:06 | 显示全部楼层
把中间那行改成
x = ((((k >> 4) << 8) >> 4) & 0x0FFF) | (k << 12) | (k >> 12);
就好了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-10-25 09:25:51 | 显示全部楼层
xieglt 发表于 2020-10-25 09:11
帮你调试了一下,找到了原因。
看图。我用了3种方式去掉高4位和低4位,
第一种

真大佬
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-10-25 22:55:45 | 显示全部楼层
我明天再看下,然后选出最佳答案,谢谢各位
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-10-26 07:24:35 | 显示全部楼层
xieglt 发表于 2020-10-25 09:11
帮你调试了一下,找到了原因。
看图。我用了3种方式去掉高4位和低4位,
第一种

我总结以下,你看看对不对:
错因是:使用算数右移导致的结果偏差  
所以解决方法是:修改代码,让编译器不使用算数右移,全部使用逻辑右移/左移 ?

所以& 0x0FFF的作用是什么,是强制转换为逻辑右移吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-10-26 07:55:32 | 显示全部楼层
本帖最后由 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位保留。
这是  按位与  运算,不是移位。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-12 21:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表