-4

版本 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);
    }
}

版本 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);
    }
}

版本 1 工作正常,但版本 2 似乎没有。我不明白为什么版本 2 坏了。取消引用双级指针与取消引用单级指针不是一回事吗,即它在指针包含的内存地址处获取值?

我将如何编写一个将 n 级指针作为输入的函数,并通过取消对 n 级指针 n-1 次的引用来返回一个 1 级指针?

4

2 回答 2

2

它们是非常不同的东西。Anint**是指向 的指针的指针int。如果你取消引用它,你会得到一个int*. Anint*是指向 的指针int。如果你取消引用它,你会得到一个int.

在第一个示例中,您将一个int**with 值0x4df73c作为第一个参数传递给work. 然后你取消引用这个,它应该给你一个int*. 也就是说,0x4df73c是地址的地址,并且这样做*pointer已经为您提供了第二个地址。int*然后,您通过添加对此进行指针算术运算,计算出字节中有(offset/sizeof(int))多少s。因此,当您添加此值时,您将继续移动以指向该偏移量。然后,您将其退回,一切都很好。intoffsetint*intint*

在第二个示例中,您0x4df73cint*. 然后你取消引用它,这给你一个int. 现在+不做指针运算 - 它做整数运算。(offset/sizeof(int))仍然会int以字节为单位为您提供 s的数量offset,但算术不会满足您的要求。它不会将 的值增加int适当的量。

假设 anint在您的机器上是 4 个字节。当你有一个int*被叫p并且你这样做p + 5时,这不只是添加5到地址中p。它增加5了 (20 字节)大小的倍数int,因此它现在指向 5th int。但是,如果你有一个int被叫i并且你做了i + 5,这真的只是添加5

所以这是你的问题。当您添加到 时int您没有进行适当的算术运算。我想如果你把它改成它起作用,假设你的系统上的 anint*和 anint大小相同(正如你所说的那样):

return (int*) (*pointer + offset);

但我不推荐这个。不要像使用int指针一样使用它。演员阵容(int*)涉及一个reinterpret_cast并且是可怕的。坚持你的第一个代码。

于 2013-04-27T19:57:35.587 回答
0

指针算术和整数算术不是一回事。

忽略写入您正在使用的位置是否有效的问题,请考虑以下结果:

int i=5;
int j=i+1; // now j==6
int* pi = &i; // let's say pi is 0x1000
int* pj = &i+1 // now pj is 0x1000 + (sizeof int)
于 2013-04-27T20:03:29.107 回答