How ptr arithmitic works??? It doesn't make any sense....

rempas rempas at tutanota.com
Sun Dec 4 16:33:35 UTC 2022


First a little bit of theory. A pointer just points to a memory 
address which is a number. So when I add "10" to this pointer, it 
will point ten bytes after the place it was pointing to, right? 
Another thing with pointers is that it doesn't have "types". A 
pointer always just points to a location so types are created for 
the compiler so we can catch bugs when pointing to places and 
trying to manipulate the bytes to a size we probably wouldn't 
want to. For example: if you have allocated 4 bytes and then you 
try to point to it with a type of "short" for example, then you 
could only manipulate 2 of these 4 bytes but you probably 
wouldn't and you did something wrong so we do have types and the 
compiler requires explicit pointer type casting (in contrast to 
C) so it can protect you from these bugs.

This type-casting brings some problem however. So, I played 
around it and I figured it out than to get the right location you 
expect when returning from a function, you need to do the math 
and then cast the whole expression (so the result) and return 
that. If you only cast the first value (that is of the different 
type) an then do that addition (or whatever expression you want), 
it will return a wrong address. But WAIT!!! This doesn't work in 
a different example. And I'm braking my head to understand why 
and I thought about asking if anyone can help and explain to me 
why. Btw, all the testing was made with `ldc` in the `BetterC` 
"mode". Code:

```d
import core.stdc.stdio;
import core.stdc.stdlib;

struct MemoryBlock {
   char* ptr;
   ulong length;
}

void* ptr = cast(void*)0x7a7;

void* right() {
   return cast(MemoryBlock*)(ptr + MemoryBlock.sizeof); // Cast 
the whole expression between paranthesis. Got the right value!
}

void* wrong() {
   return cast(MemoryBlock*)ptr + MemoryBlock.sizeof; // First 
cast the `ptr` variable and then add the number. Got a wronge 
value...
}

char* return_address_wrong() {
   MemoryBlock* local_ptr = cast(MemoryBlock*)ptr;
   return cast(char*)(local_ptr + MemoryBlock.sizeof); // Casted 
the whole expression. BUT GOT THE WRONG VALUE!!!! Why???
}

char* return_address_right() {
   MemoryBlock* local_ptr = cast(MemoryBlock*)ptr;
   return cast(char*)local_ptr + MemoryBlock.sizeof; // Now I 
first casted the `local_ptr` variable and then added the number 
but this time this gave me the right value....
}

extern (C) void main() {
   printf("EXPECTED LOCATION: %p\n", ptr + MemoryBlock.sizeof);
   printf("RIGHT LOCATION: %p\n", right());
   printf("WRONG LOCATION: %p\n", wrong());

   printf("RETURNED ADDRESS (wrong): %p\n", 
return_address_wrong());
   printf("RETURNED ADDRESS (right): %p\n", 
return_address_right());
}
```




More information about the Digitalmars-d-learn mailing list