Предположительно struct malloc_chunk
выглядит примерно так:
struct malloc_chunk {
/* ... fields here ... */
struct malloc_chunk *fd;
struct malloc_chunk *bk;
/* ... more fields here ... */
};
... и тип ->bins
выглядит следующим образом:
struct {
struct malloc_chunk *fd;
struct malloc_chunk *bk;
};
Макрос bin_at
превращает указатель на последнюю структуру в поддельный указатель на прежнюю структуру, чтобы получить доступ только к элементам fd
и bk
(поскольку они единственные, которые существуют в меньший). то есть bin_at(m, i)->fd
и bin_at(m, i)->bk
совпадают с m->bins[(i - 1) * 2].fd
и m->bins[(i - 1) * 2].bk
, но bin_at
можно использовать в местах, где ожидается struct malloc_chunk *
(при условии, что они используют только fd
и bk
члены).
Это что-то вроде хака. Я бы не стал делать это в вашем собственном коде - помните совет Кернигана о том, как писать код как можно умнее:
"Отладка вдвое сложнее, чем запись
код в первую очередь.
Поэтому, если вы напишите код как
умно, насколько это возможно, вы, по
определение, недостаточно умное для отладки
это. "- Брайан В. Керниган
ОК, так что ->bins
это вообще не массив структур - это массив struct malloc_chunk *
.
Обратите внимание, что ->bins[(i - 1) * 2]
относится к i-й паре из struct malloc_chunk *
указателей в массиве ->bins
. Эта пара эквивалентна паре указателей fd
и bk
в struct malloc_chunk
, причем первая (->bins[(i - 1) * 2]
) эквивалентна fd
(вместо этого они могли бы сделать ->bins
массивом меньшего размера). структура, которую я предложил выше, она будет функционально эквивалентной и, вероятно, более понятной)
Макрос bin_at
позволяет коду вставить одну из тех пар указателей, которые есть в массиве ->bins
, в связанный список структур struct malloc_chunk
- без выделения всего struct malloc_chunk
. Это экономия места, о которой они говорят.
Макрос bin_at
берет индекс в массив bins
и затем "если этот указатель был на самом деле значением fd
в struct malloc_chunk
, то вычислить указатель на то, где будет struct malloc_chunk
" , Это делается путем вычитания смещения члена fd
в пределах struct malloc_chunk
из адреса элемента в массиве bins
.
Это на самом деле не «находит bins[i]
» - это просто (&bins[i]
). На самом деле он находит воображаемый struct malloc_chunk
, bins[i]
которого является fd
членом.
Извините, это сложно объяснить, потому что это сложная концепция.