简体   繁体   中英

What is the difference between a void* and *(void**)?

I was programming an aligned_malloc implementation in C++ and mainly use the following code, which can be found in various places on the Interwebs, including SO:

void * aligned_malloc(size_t size, int align) {
    if (align < 0) {
        return NULL;
    }

    void *ptr;
    void *p = malloc(size + align - 1 + sizeof(void*));

    if (p != NULL) {
        ptr = (void*) (((ptrdiff_t)p + sizeof(void*) + align -1) & ~(align-1));
        *((void**)((ptrdiff_t)ptr - sizeof(void*))) = p;
        return ptr;
    }
    return NULL;
}

void aligned_free(void *p) {
    void *ptr = *((void**)((ptrdiff_t)p - sizeof(void*)));
    free(ptr);
    return;
}

I get the *(void**) in the aligned_malloc . My misunderstanding is with the cast in the aligned_free . Since we just want the value and don't have to assign to it why not use

void *ptr = ((void*)((ptrdiff_t)p - sizeof(void*)));

instead of

void *ptr = *((void**)((ptrdiff_t)p - sizeof(void*)));

I thought it was the same but when I tried the first one with an alignment of 64 it gave me an error, but when I tried the second cast the program worked correctly. So what is the difference between the two? I left out the proper C++ casts for the sake of readability.

Let us simplify the code:

int x = 7;
void * p = &x;
void * q = &p;

And now let us draw a diagram:

  +---+
x | 7 |
  +---+
    ^ 
    |
  +-|-+
p | * |
  +---+
    ^ 
    |
  +-|-+
q | * |
  +---+

Do you see how p and q are not equal? If you have q , and you want to get to p , you have to dereference q . But since a void* cannot be dereferenced, you have to promise the type system that it will find another pointer after the dereference, hence the cast to void** before the dereference.

assert(q != p);
assert(*(void**)q == p);

Should be clearer if you replace

void *ptr = *((void**)((ptrdiff_t)p - sizeof(void*)));

with the equivalent

void *ptr = ((void**)((ptrdiff_t)p - sizeof(void*))) [0];

The * is not part of any cast, it is dereferencing a pointer. It's reading data from memory.

On the other hand, you should get a really good book about C++ and look at the functions that are built into the C++ library. That's much more likely to work without problems. Using malloc_aligned means you have two classes of pointers, those allocated by malloc and those allocated by malloc_aligned, and both are incompatible.

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