Version 1:
int* work(int** pointer, int offset)
{
return *pointer + (offset/sizeof(int));
}
int main()
{
int** pointer = (int**) 0x4df73c;
int offset = 0xf4;
int* healthLowestPointer = work(pointer, offset);
while(true) {
*healthLowestPointer = 1000;
Sleep(250);
}
}
Version 2:
int* work(int* pointer, int offset)
{
return (int*) (*pointer + (offset/sizeof(int)));
}
int main()
{
int* pointer = (int*) 0x4df73c;
int offset = 0xf4;
int* healthLowestPointer = work(pointer, offset);
while(true) {
*healthLowestPointer = 1000;
Sleep(250);
}
}
Version 1 works correctly, but version 2 doesn't seem to. I don't understand why version 2 is broken. Isn't dereferencing a a double-level pointer the same thing as dereferencing a single-level pointer i.e. it grabs the value at the memory address the pointer contains?
How would I write a function that takes a n-level pointer as input, and returns a 1-level pointer by dereferencing the n-level pointer n-1 times?
They are very different things. An int**
is a pointer to a pointer to an int
. If you dereference it, you get an int*
. An int*
is a pointer to an int
. If you dereference it, you get an int
.
In the first example, you pass an int**
with value 0x4df73c
as the first argument to work
. You then dereference this, which should give you an int*
. That is, 0x4df73c
is the address of an address and doing *pointer
has gotten you the second addess. You then do pointer arithmetic with this int*
by adding (offset/sizeof(int))
, which works out how many int
s there are with offset
bytes. So when you add this value, your int*
will move along to point at the int
at that offset. You then return this int*
and all is well.
In the second example, you pass 0x4df73c
as an int*
. You then dereference it, which gives you an int
. Now the +
doesn't do pointer arithmetic - it does integer arithmetic. (offset/sizeof(int))
will still give you the number of int
s in offset
bytes, but the arithmetic won't do what you want. It won't increase the value of the int
by the appropriate amount.
Let's say an int
is 4 bytes on your machine. When you have an int*
called p
and you do p + 5
, this doesn't just add 5
to the address in p
. It adds 5
times the size of an int
(20 bytes), so that it's now pointing at the 5th int
. However, if you have an int
called i
and you do i + 5
, this really does just add 5
.
So that's your problem. When you add to the int
, you're not doing the appropriate arithmetic. I imagine it would work if you change it to, assuming an int*
and an int
are the same size on your system (as you say they are):
return (int*) (*pointer + offset);
but I do not recommend this. Don't use an int
as though it were a pointer. The cast to the (int*)
involves a reinterpret_cast
and is horrible. Stick to your first code.