You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言binary_print函数逐行原理解析(出自《黑客之道》)

binary_print 函数实现逻辑全解析

这个函数出自《黑客之道:漏洞发掘的艺术》,核心功能是把输入的32位无符号整数,按从高字节到低字节的顺序,以空格分隔的8位一组二进制格式打印输出,比如输入0x12345678会输出 00010010 00110100 01010110 01111000。

mask 与 shift 变量的作用

两个变量配合完成32位整数中单字节的逐段提取,从最高位字节开始依次处理到最低位字节:

  • mask初始值为0xff000000,二进制形式为最高8位全1、剩余24位全0。和目标值做按位与运算时,会把当前不需要处理的位全部清零,只保留待处理字节的原始值。
  • shift初始值为256*256*256即2^24(数值为16777216),作用是把mask筛选出来的、位于高位的8个比特,通过整数除法移动到最低8位的位置,最终得到一个0~255之间的独立字节值。
  • 每处理完一个字节,两个变量都除以256,等价于二进制右移8位:mask会依次变为0x00ff0000、0x0000ff00、0x000000ff,分别对应从高到低的第二、第三、第四个字节;shift对应变为216、28、2^0,刚好匹配每个字节需要移位的长度。

byte = (value & mask) / shift; 运行原理

这行代码就是前面说的单字节提取逻辑,结果恒为0的误解是不成立的,拿实际值举例就很清楚:
假设输入value = 0x12345678,对应32位二进制为00010010 00110100 01010110 01111000:

  1. 第一次外层循环:value & mask = 0x12345678 & 0xff000000 = 0x12000000,除以shift=2^24后得到0x12(十进制18),也就是最高位的字节值。
  2. 第二次外层循环:mask和shift都除以256,value & mask = 0x00340000,除以shift=2^16后得到0x34(十进制52),也就是第二个字节值。
  3. 后两次循环同理,会依次提取出第三个字节0x56、第四个字节0x78。

这里用整数除法代替位移是作者的写法习惯,对于无符号整数来说,除以2^n和右移n位的运算结果完全一致。

byte & 0x80 分支判断逻辑

0x80的二进制形式是10000000,刚好是单个字节中最高位(第7位,从0开始计数)为1、其余位为0的掩码,这段分支配合内层循环完成单字节的逐位打印:

  • 拿当前保存的单字节值和0x80做按位与,如果结果非0,说明当前字节的最高位是1,打印字符'1';如果结果为0,说明最高位是0,打印字符'0'。
  • 打印完一位后执行byte *= 2,等价于把字节的所有位左移1位:原来的次高位会移动到最高位的位置,原来的最高位被移出丢弃。循环8次,就能把一个字节的8个比特从高位到低位依次打印出来。

还是拿字节值0x12(二进制00010010)举例:

  1. 第一次判断:00010010 & 10000000 = 0,打印0,左移后字节变为00100100
  2. 第二次判断:00100100 & 10000000 = 0,打印0,左移后字节变为01001000
  3. 第三次判断:01001000 & 10000000 = 0,打印0,左移后字节变为10010000
  4. 第四次判断:10010000 & 10000000 = 非0值,打印1,左移后字节变为00100000
  5. 后续四次循环依次打印0、0、1、0,最终拼出的二进制串就是00010010,和原字节完全一致。

整个函数的执行流程就是外层4次循环每次处理1个字节,字节前打印空格做分隔,内层8次循环逐位打印当前字节的比特,全部处理完就得到了完整的32位二进制表示。

内容的提问来源于stack exchange,提问作者SUD pythonism

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 09:18:17