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 thanlen
. Thus, the bitwise&
has no effect, as any number less than0x800
anded with0x7FF
is the number itself.out > in
: In this case, the result is a negative number, between0
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
.
精彩评论