Объяснение кода C - PullRequest
       2

Объяснение кода C

1 голос
/ 27 января 2011

Что означает следующий код:

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);?

Ответы [ 3 ]

2 голосов
/ 27 января 2011

Функция возвращает пространство, доступное для чтения, в кольцевом буфере с степенью двойки.

1 голос
/ 27 января 2011

Оператор & вернет логическое И (бит на бит) между вашими значениями bp->in - bp->out и bp->len - 1.

0 голосов
/ 27 января 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...