Day 0014 - GameMemory cast to (uint8 *)

Hello there!

I've been coding along with the series up to day 14, and though I understand ~80% of the code, there is one particular aspect of Day 0014's code that I don't get. It has to do with this line:

1
GameMemory.TransientStorage = ((uint8 *)GameMemory.PermanentStorage + GameMemory.PermanentStorageSize);


For reference, all related code (split across various files):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#if INTERNAL_BUILD
                LPVOID BaseAddress = (LPVOID)Terabytes((uint64)2);
#else
                LPVOID BaseAddress = 0;
#endif
                game_memory GameMemory = {};

                GameMemory.PermanentStorageSize = Megabytes(64);
                GameMemory.TransientStorageSize = Megabytes(512);

                uint64 TotalMemorySize = GameMemory.PermanentStorageSize + GameMemory.TransientStorageSize;

                GameMemory.PermanentStorage = VirtualAlloc(BaseAddress, TotalMemorySize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
??? -->>        GameMemory.TransientStorage = ((uint8 *)GameMemory.PermanentStorage + GameMemory.PermanentStorageSize);


and

1
2
3
4
5
6
7
8
9
struct game_memory {
    bool IsInitialized;

    uint64 PermanentStorageSize;
    void* PermanentStorage;

    uint64 TransientStorageSize;
    void* TransientStorage;
};


Here's my current understanding of the code:

We allocate a block of memory of size=permanentsize + transientsize. The struct game_memory contains a pointer to the start our permanent storage and a pointer to the start of our transient storage, it also has the sizes for both chunks of memory. In this line:

1
GameMemory.TransientStorage = ((uint8 *)GameMemory.PermanentStorage + GameMemory.PermanentStorageSize);


We're clearly computing the TransientStorage pointer, in other words: where our transient storage starts in the chunk of memory we allocated. However, I don't get why we're casting the PermanentStorage pointer to a uint8 pointer, I can't even begin to try and explain why we're doing that. Isn't the TransientStorage simply located at the end of the PermanentStorage? Or am I fundamentally misunderstanding what we're doing here?

Many thanks in advance for any help!

Edited by mcalis on
To summarize what it sounds like you already understand, we allocated a large block of memory big enough for both TransientStorage and PermanentStorage. GameMemory.PermanentStorage points to the start of this block and we want GameMemory.TransientStorage to point to GameMemory.PermanentStorageSize bytes after it.

It seems like the obvious way to do this would be simply

1
GameMemory.TransientStorage = GameMemory.PermanentStorage + GameMemory.PermanentStorageSize;


However, we have to understand how pointer arithmetic works in C. When we add X to a pointer, the compiler doesn't just add X bytes to the pointer's location. It adds X * the size of whatever the pointer is pointing to.

So when this code is compiled and run

1
2
short* ptr_a = (short*)10;
short* ptr_b = ptr_a + 2;


ptr_b will be set to 14, as a short is 2 bytes big.

Now we have a problem - GameMemory.PermanentStorage is of type void*. void* means "This doesn't point to a specific type". void doesn't have a size, so you can't do pointer arithmetic on it. If I change the shorts above to void and actually try to compile in Visual Studio I get this error.

1
error C2036: 'void *' : unknown size


And indeed, looking back at this line

1
GameMemory.TransientStorage = GameMemory.PermanentStorage + GameMemory.PermanentStorageSize;


If we just tried to compile as is, we would get the same error. Now because we want to go PermanentStorageSize bytes forward, we can cast PermanentStorage to a type that is 1 byte big, like uint8, and then add to it. So we get the final line

1
GameMemory.TransientStorage = ((uint8 *)GameMemory.PermanentStorage + GameMemory.PermanentStorageSize);



Hope that helps!
That certainly helps! Thanks for the eloborate explanation!