2012-05-26 27 views
4

此代码来自K & R书 - 第8章第7节:示例 - 存储分配器。这段代码至少对我来说没有意义。 “Header”是一个结构体和一个“限制性最强的对齐类型”的联合,这是一种长类型。然后,Malloc将找到一个足够大的可用空间,其大小为标题大小的倍数。K&R malloc代码没有意义吗?

static Header base;   /* empty list to get started */ 
static Header *freep = NULL; /* start of free list */ 

/* malloc: general-purpose storage allocator */ 
void *malloc(unsigned nbytes) 
{ 
    Header *p, *prevp; 
    Header *morecore(unsigned); 
    unsigned nunits; 
    nunits = (nbytes+sizeof(Header)-1)/sizeof(Header) + 1; 
    if ((prevp = freep) == NULL) {  /* no free list yet */ 
    base.s.ptr = freeptr = prevptr = &base; 
    base.s.size = 0; 
    } 
    for (p = prevp->s.ptr; ; prevp = p, p = p->s.ptr) { 
    if (p->s.size >= nunits) { /* big enough */ 
     if (p->s.size == nunits) /* exactly */ 
     prevp->s.ptr = p->s.ptr; 
     else {  /* allocate tail end */ 
     p->s.size -= nunits; 
     p += p->s.size; 
     p->s.size = nunits; 
     } 
     freep = prevp; 
     return (void *)(p+1); 
    } 
    if (p == freep) /* wrapped around free list */ 
     if ((p = morecore(nunits)) == NULL) 
     return NULL; /* none left */ 

    } 
} 

这段代码的奇数部分是语句nunits = (nbytes+sizeof(Header)-1)/sizeof(Header) + 1;,然后在比较if (p->s.size >= nunits)用于查找单位一个足够大的空间,在头部的大小方面。前者不应该只是nunits = (nbytes+sizeof(Header))/sizeof(Header)?原始代码将评估为比它应该低的值。什么是+ -1s?为什么分配空间比想要的少。

+1

保持运营商的优先考虑,并再次分析... –

+6

@duffymo:而不是告诉我,你不能告诉我代码如何工作?顺便说一句,你读过那本书吗?注意到很多错别字?但没有人对此说过任何话。 – 1der

+0

假设这是第一次调用'malloc',并且您已经请求了1个字节,即'malloc(1)',并且看到了哪些'nunits'返回了您的建议修正和书中的代码。 – dirkgently

回答

10

-1+1将计算不与块大小相乘的值。

例如,假设块大小为10。如果尝试使用公式n/10获得所需的块的数目,那么你将得到对于n 1个块= 15。这是错误的,就需要2

如果您更改公式为n/10 + 1那么它也将是错误的。当n = 20时,只需要2个块,但该公式将返回3.

正确的公式是(n - 1)/10 + 1。这就是你用整数除法的方法。唯一与此不同的是,您询问的公式是额外的sizeof(Header),这只是标题本身所需的额外空间。

+0

谢谢这真的有帮助。其实这个混淆是由于我把分割符号'/'作为一个整体单元后的表达式。 – 1der

+0

使用'(n + 9)/ 10'会不会更简单? –

+0

@JoshuaGreen:是的,这就是我通常使用的。 –

3

(nbytes+sizeof(Header)-1)/sizeof(Header) + 1在代码中是一个非常标准的习惯用法,用正确的四舍五入得到某些东西的单位数。它用一些值来尝试它,你会发现它能正常工作。

实际成语最好表示为(nbytes - 1)/unitSizeInBytes + 1

为了澄清,根据接受的答案的最后一段,sizeof(Header)的使用是不同的两个部门。它在分红中的用途是因为它需要为Header和nbytes分配字节。它在除数中的用途是因为这是分配块的大小。发生在这种情况下,它们是相同的值,sizeof(Header)

+0

是的,正如K-ballo所说的,考虑运营商的优先级。 –

+0

这是否意味着我应该阅读别人的代码以熟悉这些标准习语? – 1der

+0

是的,并且提出这样的问题也是一个好主意,但在你做之前要仔细研究。阅读好的开源代码。然后工作。让世界变得更美好。 :) –