Разработка моего комментария: я полагаю, что этот фрагмент взят из встроенной реализации TCP / IP, найденной в netutil.c . Если это правильно, 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
.