I'm reading C on disk hash table code without knowing much about C or mmap
but i know Golang.
This piece of code confuses me. There are two structs like this.
typedef struct HashTbl
{
void *data;
...
} HashTbl;
typedef struct Header
{
char magic[16];
size_t total;
size_t used;
} Header;
It uses mmap
to map HashTbl
data
property
ht->data = mmap(NULL, data_size, prot, MAP_SHARED, file, 0);
ht
type is HashTbl
, ht->data
would be cast to Header
to set property value like this:
Header *h = (Header *)ht->data;
strcpy(h->magic, MAGIC_STR);
h->total = 12;
h->used = 0;
Then this function:
void *hashtable_of(HashTbl *ht)
{
return (unsigned char *)ht->data + sizeof(Header);
}
usage of this function:
uint64_t *table = (uint64_t *)hashtable_of(ht);
I don't understand what's the purpose of this function, is that to calculate the length of void pointer (Header::data)
value?
void pointer
in C seems like interface{}
in Go, which could be cast to any type.
but Go has error handling while doing type casting, if we cast interface{}
type to wrong type, it would return the error
But in this C code, it casts a Struct
-> unsigned char pointer
and combine it to sizeof
other struct, which means unsigned char pointer
is an integer?!
How is that even possible?
it casts a
Struct
->unsigned char pointer
and combine it to sizeof other struct, which means unsigned char pointer is an integer?
void *hashtable_of(HashTbl *ht)
{
return (unsigned char *)ht->data + sizeof(Header);
}
Not quite. Code is starting with one pointer, ht
and determining another pointer, the return pointer.
There is not cast of a struct
. There is a cast of a unsigned char *
.
There are no integers in this code aside from sizeof(Header)
.
Let us take it in steps:
The pointer ht
has member .data
which is de-referenced by ht->data
. That results in a void *
.
The void *
is cast to an unsigned char
pointer.
Next, code performs pointer addition with ... + sizeof(Header)
. Pointer addition is like integer addition, yet has differences. Here the addition of a pointer and integer results in another unsigned char
pointer that is sizeof(Header)
bytes (unsigned char
) further along in memory.
Lastly this unsigned char
pointer is converted to a void *
as part of the return
.
hashtable_of()
overall usage is unclear without the surrounding code.
void pointer
in C seems like interface{} in Go, which could be cast to any type.
Almost. A void
pointer can be cast to any object pointer with restrictions of value validity and alignment. A void
pointer may be insufficient to represent a function pointer though. C lacks a 100% portable universal pointer.