简体   繁体   中英

Mmap, void pointer and type casting in C

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM