Danmoits 发表于 2020-10-24 18:33:40

将无符号整数的高四位和低四位交换,帮忙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: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;
}

xieglt 发表于 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   汇编代码是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,导致最高位保留造成的。

shooan 发表于 2020-10-25 09:25:06

把中间那行改成
x = ((((k >> 4) << 8) >> 4) & 0x0FFF) | (k << 12) | (k >> 12);
就好了

shooan 发表于 2020-10-25 09:25:51

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


真大佬

Danmoits 发表于 2020-10-25 22:55:45

我明天再看下,然后选出最佳答案,谢谢各位

Danmoits 发表于 2020-10-26 07:24:35

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


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

所以& 0x0FFF的作用是什么,是强制转换为逻辑右移吗

xieglt 发表于 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位保留。
这是按位与运算,不是移位。
页: [1]
查看完整版本: 将无符号整数的高四位和低四位交换,帮忙debug一下