Dereferencing void pointers

Hi all!

I want to know how to dereference a void pointer through the way of typing it.

Lets just say that I malloc'd a huge bunch of memory and i can do whatever i want
void* randomData = malloc ( 1000000 );

And i decide to make my own virtual 'int'
Im not sure how to do this.

*( int* ) ( randomData + 10 ) = ( int ) 323453 //323453 can be an int variable aswell

Im not sure if this is the right way to do perform a dereference.

This is an overview of what has to be done:
-The pointer has to be dereferenced
-Cast the pointer as an int pointer so we can change it like a normal 4-byte int
-Perform pointer arithmetic, so that the int can be placed anywhere we want

I hope I explained myself well, let me know if i havent...

EDIT: Forgot to mention that this is plain and pure C, no C++ involved

Many thanks!
SuperStinger
Last edited on
You can't do pointer arithmetic on a void pointer. That wouldn't make any sense, as pointer arithmetic is defined by the size of the type being pointed to.

 
*(((int*) randomData) + 10)


Basically, you just need to cast the void pointer to a real type before you do any arithmetic on it.
when working with arbitrary buffers it's common to store it as an unsigned char. This is because an unsigned char is a single byte which is the lowest level you'll work with.
> Lets just say that I malloc'd a huge bunch of memory and i can do whatever i want
> And i decide to make my own virtual 'int'
> Forgot to mention that this is plain and pure C, no C++ involved

Whether it is C or C++, alignment requirements have to be met.

I do not know how to get equivalent functionality in C (does it have an alignof keyword?), but this is how we could do it in C++.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <memory>

template < typename T >
T* allocate_from_raw_storage( void*& ptr, std::size_t& available )
{
    const std::size_t available_before = available ;

    // http://en.cppreference.com/w/cpp/memory/align
    if( std::align( alignof(T), sizeof(T), ptr, available ) == nullptr )
        throw "not enough memory" ;

    if( available_before - available )
        std::cout << available_before - available << " bytes were used for alignment and " ;
    std::cout << sizeof(T) << " bytes were used for the object\n" ;

    T* p = reinterpret_cast<T*>(ptr) ;
    ptr = static_cast<char*>(ptr) + sizeof(T) ;
    available -= sizeof(T) ;
    return p ;
}

int main()
{
    const std::size_t BUFFSZ = 1000 ;
    void* buffer = new char[BUFFSZ]{} ;

    void* next = buffer ;
    std::size_t szavail = BUFFSZ ;
    std::cout << "   next available address: " << next << "   bytes remaining: " << szavail << "\n\n" ;

    int* pi = allocate_from_raw_storage<int>( next, szavail ) ;
    std::cout << "pi: " << pi << "   next available address: " << next << "   bytes remaining: " << szavail << "\n\n" ;

    double* pd = allocate_from_raw_storage<double>( next, szavail ) ;
    std::cout << "pd: " << pd << "   next available address: " << next << "   bytes remaining: " << szavail << "\n\n" ;

    short* ps = allocate_from_raw_storage<short>( next, szavail ) ;
    std::cout << "ps: " << ps << "   next available address: " << next << "   bytes remaining: " << szavail << "\n\n" ;

    struct alignas(16) A { int a[4] ; };
    A* pa = allocate_from_raw_storage<A>( next, szavail ) ;
    std::cout << "pa: " << pa << "   next available address: " << next << "   bytes remaining: " << szavail << "\n\n" ;
}

http://coliru.stacked-crooked.com/a/96f2a07ee5182d7e

Note: clang++ with libc++ (The GNU library is way behind the rest of the word).
@JLBorges
Since malloc is not provided the type, the pointer it returns is always correctly aligned for all builtin types (SIMD excluded).
> the pointer it returns is always correctly aligned for all builtin types

Yes. But how is that relevant here?

The memory to which p points, after char* p = malloc(1000) ; // C is suitably aligned for storage of an int (or any type that is not over-aligned).

How does that make memory at p + n, where n is not an integral multiple of the alignment for int, suitable for storing an int?

Thank you all for your replies!

I am slightly confused to the casting of the pointer...

How does pointer arithmetic work?
if i say
randomData + 10

doesnt this mean that it is the pointer 'randomData' + 10 bytes after that?

Isnt there a way to use any sort of data type inside that malloc?
So if i 'reserved' 4 bytes for an int and then 20 bytes for a struct inside the data that was provided by malloc, couldnt i just return pointers from those places inside the malloc'd data, so that the program 'thinks' that its just normally allocated data?

EDIT: I just read a bit up on padding, I understand now that i cant just chuck an int variable in a random pointer ( e.g. 0x13247 )
Last edited on
SuperStinger wrote:
if i say
randomData + 10

doesnt this mean that it is the pointer 'randomData' + 10 bytes after that?
When you add to a pointer, it does not shift the pointer by bytes - it shifts it by whole increments of the type it points to. If it points to a type which is 4 bytes, then adding 3 to it will shift it by 12 bytes.
thanks L B, i gave that a test and you are clearly correct :P

Things are a little bit clearer now, thanks everyone!
Topic archived. No new replies allowed.