C代码的说明

以下代码的含义是什么:

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

我知道bp->in - bp->out表示inout之间的差异,但它与& (bp->len - 1);有什么关系& (bp->len - 1);

该函数返回可用于在二次幂大小的环形缓冲区中读取的空间。

&运算符将返回值bp->in - bp->outbp->len - 1之间的逻辑AND(每位数)。

阐述我的评论:我相信这个片段来自netutil.c中的嵌入式TCP / IP实现。 如果这是正确的, CBUFF在netutil.h中定义为:

 /* 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; 

似乎inout成员在缓冲区中是偏移量,“指向”in和out数据开头的位置。 由于这是一个循环缓冲区,因此在从中减去out有两种可能性(可能是确定传入数据长度的方法):

  • in > out :结果是一个小于len的正数。 因此,按位&无效,因为任何小于0x800的数字与0x7FF的数字本身。
  • out > in :在这种情况下,结果是负数,介于0-len之间; 传入的数据“环绕”循环缓冲区。 这比较复杂,因为它依赖于负数如何在内存中表示。 一些例子可能有助于阐明正在发生的事情(回想一下,十进制中的0x800是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) 

如您所见,这是一种简单的技术,可以“展开”循环缓冲区并检索输入和out之间的有效距离。