程序如下,第一种方式是强制指针转换,再取结构体成员;第二种方式是简单的移位。前面这种写法得考虑大小端序, 后者不用管.

#include <stdio.h>#define hi8(x)    ((( struct { unsigned char l; unsigned char h; } *)(&x))->h)
#define lo8(x)    ((( struct { unsigned char l; unsigned char h; } *)(&x))->l)
#define hi8a(x)    (((x) >> 8) & 0xff)
#define lo8a(x)    ((x) & 0xff)int main(void)
{unsigned short x;scanf("%4x", &x);                     // 不能用字面量测试, 否则-Os编译时会直接给求值了printf("%2X %2Xn", hi8(x), lo8(x));printf("%2X %2Xn", hi8a(x), lo8a(x));return 0;
}

分别用mingw-gcc, arm-none-eabi-gcc, -O0和-Os选项编译,得到的汇编如下(只取scanf到第二次printf之间的部分)

mingw-gcc, -O0, 前者9条指令, 后者10条指令. 有点呆萌是吧...

  call    _scanflea   eax, [esp+30]movzx eax, BYTE PTR [eax]movzx    edx, allea  eax, [esp+30]movzx eax, BYTE PTR [eax+1]                   ; 这里错开1字节取值movzx   eax, almov  DWORD PTR [esp+8], edxmov  DWORD PTR [esp+4], eaxmov  DWORD PTR [esp], OFFSET FLAT:LC1      ; LC1是printf的格式字符串call    _printfmovzx    eax, WORD PTR [esp+30]movzx    eax, axmovzx    edx, almovzx    eax, WORD PTR [esp+30]shr  ax, 8                      ; 移位movzx    eax, axmovzx    eax, almov  DWORD PTR [esp+8], edxmov  DWORD PTR [esp+4], eaxmov  DWORD PTR [esp], OFFSET FLAT:LC1call    _printf

mingw-gcc, -Os, 前者5条指令, 后者6条指令.

    call    _scanfmovzx eax, BYTE PTR [esp+30]mov  DWORD PTR [esp], OFFSET FLAT:LC1   ; 常量入栈提到前面了mov   DWORD PTR [esp+8], eaxmovzx    eax, BYTE PTR [esp+31]               ; 取值错开1字节mov  DWORD PTR [esp+4], eaxcall _printfmov  ax, WORD PTR [esp+30]mov   DWORD PTR [esp], OFFSET FLAT:LC1movzx   edx, almovzx    eax, ah                          ; 这次把移位优化掉了, 直接利用ax寄存器的高低位.mov DWORD PTR [esp+8], edxmov  DWORD PTR [esp+4], eaxcall _printf

arm-none-eabi-gcc, -O0, 前者8条指令, 后者10条指令:

   bl  scanfsub    r3, fp, #6ldrb  r3, [r3, #1]    @ zero_extendqisi2mov  r2, r3sub   r3, fp, #6ldrb  r3, [r3]    @ zero_extendqisi2           ; 错开1字节ldr    r0, .L3+4                     ; .L3+4是printf的格式字符串mov r1, r2mov   r2, r3bl    printfldrh  r3, [fp, #-6]mov    r3, r3, lsr #8mov   r3, r3, asl #16mov  r3, r3, lsr #16and  r2, r3, #255ldrh    r3, [fp, #-6]and    r3, r3, #255ldr r0, .L3+4mov   r1, r2mov   r2, r3bl    printf

arm-none-eabi-gcc, -Os, 这个清爽多了, 前者3条指令, 后者4条指令.

 bl  scanfldrb   r1, [sp, #7]    @ zero_extendqisi2ldrb r2, [sp, #6]    @ zero_extendqisi2    ; 错开1字节mov   r0, r4                   ; .L3+4被提前放进r4了bl printfldrh  r1, [sp, #6]mov r0, r4mov   r1, r1, lsr #8             ; 移位ldrb r2, [sp, #6]    @ zero_extendqisi2bl   printf

avr-gcc呢, 太长就不贴了. 不过-Os时反倒是移位方式的指令更少.

总之以上四种情况都是前者好些. 不过实际运行时也不一定, 没准后者更快呢?

----------------2020.2.22补充-------------------

还有一个重要的区别:前者可以作为左值,后者不行。

如下程序:

#include <stdio.h>#define hi8(x)    ((( struct { unsigned char l; unsigned char h; } *)(&x))->h)
#define lo8(x)    ((( struct { unsigned char l; unsigned char h; } *)(&x))->l) int main(void)
{unsigned short x = 0x1234;hi8(x)--;lo8(x)++;printf("%xn", x);return 0;
}

运行,结果是1135。

取pi的前8位的解压密码_两种方式实现取16位变量的高低8位, 不严谨对比相关推荐

  1. lcd取模如何取16位_两种方式实现取16位变量的高低8位, 不严谨对比

    程序如下,第一种方式是强制指针转换,再取结构体成员:第二种方式是简单的移位.前面这种写法得考虑大小端序, 后者不用管. #include <stdio.h>#define hi8(x) ( ...

  2. python武功秘籍解压密码_武林秘籍

    你好,我是一名极客!一个 75 后的老工程师! 我将花两分钟,表述清楚我喊你来这里的目的! 如果你看过武侠小说,你可以把这个经历理解为,你失足落入一个山洞遇到了一位垂暮 的老者!而这位老者打算传你一套 ...

  3. 详解SpringCloud-gateway动态路由两种方式,以及路由加载过程

    gateway配置路由主要有两种方式,一种是用yml配置文件,一种是写代码里,这两种方式都是不支持动态配置的.如: 下面就来看看gateway是如何加载这些配置信息的. 1 路由初始化 无论是yml还 ...

  4. 流沙解压密码_在流沙的基础上:总结

    流沙解压密码 by Shubheksha 通过Shubheksha 在流沙的基础上:总结 (Building on Quicksand: A Summary) Let's try to break d ...

  5. python武功秘籍解压密码_压缩解压

    Linux下最常用的打包程序就是tar了,使用tar程序打出来的包我们常称为tar包,tar包文件的命令通常都是以.tar结尾的.生成tar包后,就可以用其它的程序来进 行压缩了,所以首先就来讲讲ta ...

  6. 树莓派python编程入门与实战解压密码_树莓派Python编程入门与实战

    目录 第一部分 树莓派编程环境 第1章 配置树莓派 3 1.1 获取树莓派 3 1.1.1 了解树莓派的历史 3 1.1.2 为什么要学习用Python 在树莓派上进行编程 4 1.2 获取树莓派 5 ...

  7. 从python开始学编程pdf 解压密码_从Python开始学编程PDF高清完整版网盘免费分享...

    提取码:szq0 image 内容简介 · · · · · · 改编自Vamei博客的<Python快速教程>.本书以Python为样本,不仅介绍了编程的基本概念,还着重讲解编程语言的主流 ...

  8. 蓝帽杯2022年半决赛 writeup(附取证题目+解压密码+附件)

    文章目录 电子取证 手机取证_1 手机取证_2 exe分析_1 exe分析_2 exe分析_3 exe分析_4 exe分析_5 apk分析_01 apk分析_02 apk分析_05 apk分析_06 ...

  9. java的websocket_java 实现websocket的两种方式实例详解

    一.介绍 1.两种方式,一种使用tomcat的websocket实现,一种使用spring的websocket 2.tomcat的方式需要tomcat 7.x,JEE7的支持. 3.spring与we ...

最新文章

  1. jQuery插件开发学习笔记
  2. boost::safe_numerics::interval相关的测试程序
  3. 【HDU - 1216 】Assistance Required (模拟,类似素数打表,不是素数问题!)
  4. memcpy,strcpy,strncpy
  5. mysql分布式如何实现原理_分布式通讯协议实现原理
  6. 解决Python编程中PyCharm无法识别导入同目录下模块问题
  7. python爬虫框架scrapy操作步骤
  8. a:link a:visited a:hover a:active四种伪类选择器的区别
  9. android+wear独立应用,谷歌更新Android Wear政策:鼓励开发可独立运行的手表应用
  10. LL1分析构造法_行测技巧:比较构造法两步轻松解决方程题
  11. react随笔-1(为什么在react使用jq无法正确渲染组件位置)
  12. 【Android输入法源码】基于GooglePinyin开源代码进行修改可运行!!!
  13. 最难忘的一节计算机课,难忘的一堂课作文(共10篇)
  14. 汇总我关注的技术博主的2021年度总结
  15. c语言内联int 21h,[X64内核]SMAP,SMEP
  16. markdown java代码块 语法_MarkDown 语法详解
  17. 美团(2) - 实战准备
  18. 我的星座分析-处女座
  19. 今日金融词汇--- 高周转模式
  20. php 按比例裁剪图片,自定义裁剪图片大小,按照一定比例裁剪图片的软件

热门文章

  1. javascript:window.showModalDialog缓存问题
  2. php向bat中传递参数,php-将参数传递给PHPUnit
  3. 华为ac控制器web配置手册_家庭WIFI网络规划设计与配置实战,一文教会你
  4. python统计分析--2.预分析:异常值、缺失值处理
  5. 微信小程序识别图片并提取文字_图片转文字识别功能的小程序,超精准识别——闪电识字...
  6. python打开setting_Django自带日志 settings.py文件配置方法
  7. zbrush 添加纹理贴图_zbrush零基础新手必看入门讲解
  8. ACM思维题训练 Section A
  9. 阿里云服务器部署SpringBoot项目(mysql安装、服务部署)
  10. 图数据集之cora数据集介绍 --- 适用于GCN任务