欢迎光临散文网 会员登陆 & 注册

C语言代码重构案例分析

2023-01-13 11:32 作者:GC_CH  | 我要投稿

    以下是我在反编译的过程中遇到的一个很有意思的函数(参数名是我修改后的, 方便大家理解), 接下来会一步一步将它重构成一个易于理解的函数.

startX, startY, width, height 都是非负数.

循环替换

    首先从最内层的循环开始

    do while 语句我们不常用, 并且它的循环条件是放在最后的, 不太利于理解循环, 如果能替换成 for 语句或 while 语句那就比较好. 对于这个循环, 熟悉代码的话很容易转成 for 循环, 初始条件是 v8 = -width, 终止条件是 v8 < 0, 修改迭代变量的语句是v8++.

    

    

合并变量

    对外层的循环做同样的处理之前, 需要先处理一下它的迭代变量 v9.

    这里对 height 的操作完全是可以去掉了. 因为, 在使用循环体内对 height 的操作出现在开始和末尾处, 而循环体的其他部分, v9 和 height 的值一直相等.

    将 v9 的初次赋值外提, 然后所有循环中 height 的地方全部用 v9 替代, 最后去掉无用代码就得到了上面的代码. 接着, 用for循环替换外层的 do while 循环.

变量替换

    这样的代码现在还不够好 : (1) 内外层的迭代变量变化量不统一, 一个是 v9--, 一个是v8++, 一个减一个加, 有点别扭; (2) 数组的索引一般是正数, 虽然用负数来索引数组是合法的, 但很容易出错, 一不小心就数组越界了.

    首先使用变量替换的方法处理外层循环, 令 y = height - v9, 则 y 的初值为0, 终止条件变为 

v9 = height - y, v9 是正数, 因而等价于 y < height, 

v9-- 等价于 y++ , 因为 v9 + y = height, y与v9的和保持不变.于是外层循环变为 :

    同理, 令 x = v8 + width, 则 x 的初值为0, 终止条件为 v8 = x - width, v8 是负数, 因而等价于x  < width, v8++等价于 x++, 因为 x - v8 = width, x 和 v8的差保持不变. 

指针与数组的转换

    这样的代码还不够完美 :

    光是看这样的代码, 还是有点难以理解对参数array做了什么.

    1. 每次外层循环, v6 增加了32, 也就是 y = 0 时初始v6指针 + 0, y = 1 时 + 32, y = 2 时 + 62. 所以, 可以将v6初值放到第一层循环中.

    32 * startY + 32 * y 可以合并为 32 * (startY + y).

    2. 使用指针运算继续将对array的操作放到第二层循环中.

v6[x - width] = *(v6 + x - width),

v6 = &array[32 * (startY + y) + startX + width] = array + 32 * (startY + y) + startX + width,

那么 *(v6 + x - width) = *(array + 32 * (startY + y) + startX + width + x - width), 消去width得到

*(array+ 32 * (startY + y) + startX + x) = array[32 * (startY + y) + startX + x]

    最终结果为

    这样, 就很容易看出来, 这个array其实是一个二维数组, 每行有32个元素, 有多少行不知道. 而这个函数的作用是将左上角为 (startX, startY), 大小为(width, height) 的区域全部设置为value.


C语言代码重构案例分析的评论 (共 条)

分享到微博请遵守国家法律