Код
pymalloc_free(void *ctx, void *p){
...
*(block **)p = lastfree = pool->freeblock;
pool->freeblock = (block *)p;
...
}
Прежде всего, block
- это typedef для uint8_t
, то есть 8-битный байт.Здесь он используется просто как семантический маркер, чтобы сказать, что указатель указывает на блок памяти для размещения вместо каких-либо случайных байтов где-либо или строки символов.
Вы спросили:
Я думал, что *(block **)p
считается идемпотентным, если p
имеет тип block*
, почему нет в этом случае.
Это не такконвертирует block *
в block **
и затем разыменовывает указатель.Обратите внимание, что в данном случае указатель является void *
, а не block *
.
- Как эти назначения работают?
доступ к памяти, на которую указывает p
, осуществляется так, как если бы он указывал на a block *
.Вместо слепков.Если бы существовала промежуточная переменная, потому что это сделало бы более очевидным, что происходит:
block **bpp = p
*bpp = lastfree = pool->freeblock;
и
bp = pool->freeblock;
block **bpp = bp;
if ((pool->freeblock = *bpp) != NULL) {
}
Это, кажется, используется для реализации связанного списка, как этот механизм работает и как он связан с * (блок **) p?
Все свободные блоки памяти простокуски байтов определенного размера.Первые sizeof (block *)
(т.е. sizeof (uint8_t *)
) байтов свободного блока указывают на следующий блок байтов, поэтому указатель на начало может быть приведен к указателю на указатель и разыменован для получения this значение указателя находится в первых байтах.
Обратите внимание, что блок должен также начинаться с адреса, который делится на _Alignof (block *)
, который pymalloc
тщательно поддерживает.