以下代码的含义是什么:
WORD len;
LWORD in;
LWORD out;
WORD buff_dlen(CBUFF *bp)
{
return((WORD)((bp->in - bp->out) & (bp->len - 1)));
}
我理解bp->in - bp->out
表示in
和out
之间存在差异,但它与& (bp->len - 1);
有什么关系?
答案 0 :(得分:2)
该函数返回可用于在二次幂大小的环形缓冲区中读取的空间。
答案 1 :(得分:1)
&
运算符将返回值bp->in - bp->out
和bp->len - 1
之间的逻辑AND(每位数)。
答案 2 :(得分:0)
阐述我的评论:我认为这个片段来自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;
似乎in
和out
成员在缓冲区中是偏移量,“指向”输入和输出数据开头的位置。由于这是一个循环缓冲区,因此从out
中减去in
有两种可能性(可能是确定传入数据长度的方法):
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)
正如您所看到的,这是一种简单的技术,可以“解包”循环缓冲区并检索in
和out
之间的有效距离。