开发者

Explanation of C code

What is the meanin开发者_如何学Cg of the following code :

WORD len;  
LWORD in;  
LWORD out;

WORD buff_dlen(CBUFF *bp)
{
    return((WORD)((bp->in - bp->out) & (bp->len - 1)));
}

I understand that bp->in - bp->out means difference between the in and out, but what relationship does it have with & (bp->len - 1); ?


The function returns the space available for reading in a ring-buffer of a power-of-two size.


The & operator will return the logical AND (bit per bit) between your values bp->in - bp->out and bp->len - 1.


Elaborating upon my comment: I believe that this snippet comes from an embedded TCP/IP implementation, found in netutil.c. If this is correct, CBUFF is defined in netutil.h as:

/* Default circular buffer size: MUST be power of 2 
** This definition is for initialisation only, and may be overriden to 
** create a larger or smaller buffer. To determine the actual buffer size, all 
** functions MUST use the 'len' value below, not the _CBUFFLEN_ definition */ 
#ifndef _CBUFFLEN_ 
#define _CBUFFLEN_ 0x800 
#endif 
/* Circular buffer structure */ 
typedef struct 
{ 
    WORD len;                   /* Length of data (must be first) */ 
    LWORD in;                   /* Incoming data */ 
    LWORD out;                  /* Outgoing data */ 
    LWORD trial;                /* Outgoing data 'on trial' */ 
    BYTE data[_CBUFFLEN_];      /* Buffer */ 
} CBUFF;

It appears as though the in and out members are offsets in the buffer, 'pointing' to the locations of the beginning of the in and out data. As this is a circular buffer, there are two possibilities when subtracting out from in (probably as a way to determine the length of the incoming data):

  • in > out: The result is a positive number less than len. Thus, the bitwise & has no effect, as any number less than 0x800 anded with 0x7FF is the number itself.
  • out > in: In this case, the result is a negative number, between 0 and -len; the incoming data 'wraps around' the circular buffer. This is trickier as it relies on how negative numbers are represented in memory. A few examples may help elucidate what is happening (recall that 0x800 in decimal is 2048):

 

bp->in-bp->out  |  representation  |  &'ed with 0x7FF   | decimal representation
----------------+------------------+--------------------+-----------------------
     -1         |      0xFFFF      |       0x07FF       |      2047 (2048-1)
     -2         |      0xFFFE      |       0x07FE       |      2046 (2048-2)
     -10        |      0xFFF6      |       0x07F6       |      2038 (2048-10)
     -2046      |      0xf802      |       0x0002       |      2    (2048-2046)
     -2047      |      0xf801      |       0x0001       |      1    (2048-2047)

As you can see, this is a simple technique to 'unwrap' the circular buffer and retrieve the effective distance between in and out.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜