美文网首页
常见的对齐算法的代码到底是什么意思?

常见的对齐算法的代码到底是什么意思?

作者: 负二98 | 来源:发表于2020-03-17 16:37 被阅读0次

1.

在c语言中,我们经常会看到一个关于内存对齐的宏:

#define ALIGN(x,n) = (((x)+(n)-1)&~((n) - 1) )

或者类似

#define ALIGN(x) = (((x)+3)&~3

第一个宏就是所谓的把 x 按 n 对齐,第二个宏只不过是把n带入具体的数字,我们可以说是把x 按 4 对齐。

宏计算的结果为,把 x 按 n 对齐时,所需要的内存大小

举例:

如果把3 按 4 对齐,那么所需内存的大小为 4,填充为1

如果把5 按 4 对齐,那么所需内存的大小为 8,填充为3

2.

要理解这个宏的具体计算原理,首先我们要知道对任意整数都有如下公式:

b = ac + r; 0<= r < a;

其中所有值都为整数。

随便带入几个数方便有一个直观的认识:若b = 8,c = 2,则 a = 3,r = 2,即 8=3 * 2 + 2;

其中的r,就是我们通常概念中的余数,同时我们可以把它叫做 最小非负剩余。仔细理解这个概念,有助于接下来的推理。

用c 语言或者其他类似语言进行计算时,我们可以得到:

a = b/c; r= b - b/a;

注意:我们讨论的所有的数字都是整数,编程语言通常在计算整数除法时,都遵守一个原则,那就是小数部分全部舍弃,

即8/3 \approx  2.67,编程语言中8/3=2,这里不会四舍五入。

最小非负剩余我们可以来试着写出最大非正剩余,即

x = qn + m; -n< m <=0;

其中r叫做最大非正剩余。

同样,随便带入几个数方便有一个直观的认识:若x = 5,n = 8,则 q = 1,m = -3,即 5=1 * 8 - 3;

推导到这里,我们发现,所谓的最大非正剩余,就是我们要讨论的核心,即把x 按 n 对齐m 的绝对值就是我们把x 按 n 对齐时,要填充的大小,同时我们的宏要求得的既是qn。

现在我们要将最大非正剩余转换成最小非负剩余,这样方便我们求qn

为了达成这个目的,我们做如下推导:

x = qn + m; -n< m <=0;

x + n = qn + m + n; 0 < m <=n;

x + n - 1 = qn + ( m + n - 1); 0=< m <n;

同时观察最大非正剩余公式:

b = ac + r; 0<= r < a;

即:

ac = qn;

b = x + n - 1;

同时在最小非负剩余的讨论中,我们还知道 a = b/c 

可得 qn = ac = b/c*c = (x + n - 1)/n*n;

3.

接下来简单介绍一些推导过程涉及到的位运算,以帮助我们把最后的推导完成。

左移:<<

作用:相当于位运算中的乘法,x 左移 n位,即 x * 2的n次幂

举例:

0011 左移 两位 为1100,即

3 << 2 = 1100 = 3 * 2的2次幂 = 3 * 4 = 12

右移:>>

作用:相当于位运算中的除法,x 右移 n位,即 x / 2的n次幂

举例:

1111 右移 两位 为0011,即

15 >> 2 = 0011 = 15 / 2的2次幂 = 15 / 4 = 3

注意,这里是我们之前讨论的整数除法,并且不会四舍五入

左移右移这两个操作有一个值得注意的地方是,移位后空位补零,也就是说1111(十进制15),右移后再左移,不会变回15,因为右移时被移除的末两位在左移后会被步零

1111 >> 2 = 0011

0011 << 2 = 1100

所以连续的右移再左移,相当于是清理了这个数字的末尾两位。

再看我们求得的公式:qn =  (x + n - 1)/n*n;

内存对齐时,通常对齐数都是2 的某次幂,也就是说我们通常都会按照4 对齐或者8对齐,在这个前提下

我们可以限定n 的范围,即 n 为 2 的某次幂

由此我们又可以得到一个结论,qn =  (x + n - 1)/n*n 相当于将 (x + n - 1) 右移 了几位后,再左移,也就是说将(x + n - 1)末尾几位清零后,得到的结果便是qn

那么是末尾几位呢?答案很明显,是以2为底,n 的对数。

举例来说就是,按 4 对齐时,要将 (x + n - 1) 的末尾 2位清零;按 8 对齐时,要将 (x + n - 1) 的末尾 3位清零。

可以带入具体数字计算一下,比如,把3 按 4 对齐,带入公式得 3 + 4 - 1 = 6,6 得二进制数据为 0110,n = 4,所以末尾2位清零,得 0100 = 4,也就是说,

如果把3 按 4 对齐,那么所需内存的大小为 4,填充为1,结果完全正确。

那么清零操作除了连续的移位操作还有什么其他的操作呢?

我们在宏中看见的 &~ 连续的两个位运算,也能达到同样的效果。

我们可以带入具体数字计算一下,宏为 (((x)+(n)-1)&~((n) - 1) )

我们还是把3 按 4 对齐,宏变为(3 + 3)&~3,其中~3 = ~0011 = 1100,6 = 0110,6&~3 = 0110 & 1100 = 0100 = 4

结果正确。

相关文章

  • 常见的对齐算法的代码到底是什么意思?

    1. 在c语言中,我们经常会看到一个关于内存对齐的宏: #define ALIGN(x,n) = (((x)+(n...

  • 编程算法之排序和查找算法

    查找和排序算法是算法的入门知识,其经典思想可以用于很多算法当中。因为其实现代码较短,应用较常见。 一. 排序 常见...

  • IOS常见算法

    常见算法: 快速排序: 选择排序: 冒泡排序: 测试代码:

  • 【C/C++】#ifdef __cplusplus extern

    时常在 cpp 文件中看到这样的代码: 这段代码到底是什么意思呢?首先,__cplusplus 是 cpp 中的自...

  • 排序算法

    常见排序算法 本文涉及的算法有:冒泡排序选择排序计数排序 冒泡排序 伪代码 流程图 选择排序 伪代码 流程图 计数...

  • 结构体内存对齐

    对象内存对齐 探讨的问题 1.什么是内存对齐?2.为什么要做内存对齐?3.结构体内存对齐规则4.源码内存对齐算法 ...

  • Xcode常用插件

    XAlign 下载地址 用于对齐规范代码:=对齐、属性对齐、宏定义对齐 对齐:shift+cmd+x 恢复:cmd...

  • 常见的数学分布与Python实现代码大全

    How to understand Distribution 机器学习算法学习基础-常见分布的Numpy代码实现 ...

  • 常见排序算法代码集锦

    冒泡排序 快速排序 归并排序 堆排序 选择排序 插入排序 希尔排序

  • 2016-06-01 今日收集

    "常见机器学习算法实现代码(DeepLearning Tutorials/PCA/kNN/logistic reg...

网友评论

      本文标题:常见的对齐算法的代码到底是什么意思?

      本文链接:https://www.haomeiwen.com/subject/uyrtyhtx.html