分析并理解此代码的作用

时间:2014-04-11 14:42:50

标签: c

长时间潜伏,第一次海报。我是一名学生,并且在两年内没有触及过编程课程。现在我再次上课,我在阅读和理解其他人的代码时遇到了困难。我在这里有一个来自HMC的示例代码,其中包含C中的一部分简单内存分配器。

void free_block(ptr p) {
     *p = *p & ~1;                         /* clear allocated flag */    
     next = (unsigned*)((char*)p + *p);    /* find next blk */   
     if ((*next & 1) == 0)                 /* if not allocated... */     
     *p += *next;                          /*   add to this block */
      }

尽管有这些评论,但我仍然对这里发生的事情感到困惑。我知道代码的作用但我自己永远无法编写代码。如果有人能够解释这段代码中的肮脏部分,我将非常感激。

2 个答案:

答案 0 :(得分:1)

由于字节对齐,分配大小不需要最后一个二进制位, 所以它被用作标志是否分配了该块。 分配的大小由块开头的值表示。

~1是1的按位反转,意味着代替0x01,它是0xFE

 *p = *p & ~1;                         /* clear allocated flag */

 0xFFFFFFFE 
(1111 1111 1111 1111 1111 1111 1111 1110)

使用当前值的按位AND运算清除最后一位。 结果是原始分配的大小。

从技术上讲,它取消引用p处地址的值,并使用0xFFFFFFFE执行按位AND运算,有效地保留所有值位,但最不重要 (如果最初的话,确保价值不再以1结尾)。

 next = (unsigned*)((char*)p + *p);    /* find next blk */   

'next'是一个指向后续位置的指针 p + [上述陈述中的结果值]

 if ((*next & 1) == 0)                 /* if not allocated... */     
    *p += *next;                          /*   add to this block */

如果'next'的二进制值不以1结尾(按位AND运算), 取'p'处的值并在'next'处添加值,并将结果分配给'p'处的位置。

因此,换句话说,如果下一个块未分配,则原始块通过将该块大小添加到自身(包括有效地删除它的存在)来包含它。

祝你好运。我希望这会有所帮助。

答案 1 :(得分:1)

这些操作可能很清楚,所以我会尝试在上下文中处理实际的解释。

*p = *p & ~1;                         /* clear allocated flag */

~运算符补充了这些位。因此,~1除了最后一位以外都是1位,因此将最后一位清零。

我们不知道为什么......但是。

next = (unsigned*)((char*)p + *p);    /* find next blk */

在这里,我们p投射到指向char(char*)p)的指针,添加到p的任何内容中。该总和被视为指向unsigned int的指针。或多或少,您将p视为与自身的偏移。

我很确定这是一个坏主意,没有很多更多的支持代码,以确保它是安全的,但你正在阅读代码,而不是写它...

if ((*next & 1) == 0)                 /* if not allocated... */

我们现在知道为什么第一行中丢弃了最低有效位。在此方案中,代码使用该位来标记已分配块。

    *p += *next;                      /*   add to this block */

在这里,我们只是将p推到我们上次分配的东西之外。

在不知道next指向的地方,我们可以猜测它正在通过某种类似链表的结构。但是,如果不知道如何填充p以及这些指针是如何构建的,那就太不稳定了。

但结果是代码声称下一个块并跳过指针。