2013-04-27 22 views
-4

版本1:2取消引用不同的行为双级指针结果从废弃一个单级指针

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

版本:

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-1次解引用n级指针返回1级指针?

+0

这两个版本是UB。 – 2013-04-27 19:44:16

+1

晚安SO,今天没有更多这些问题.../OFF – 2013-04-27 19:44:59

+0

@Armin:我不确定你的意思。版本1是一致的并始终有效。 – user2327287 2013-04-27 19:45:11

回答

2

他们是非常不同的东西。 int**是指向指向int的指针的指针。如果你解除引用,你会得到一个int*int*是指向int的指针。如果你解除引用,你会得到一个int

在第一个示例中,您将一个int**的值为0x4df73c作为work的第一个参数。然后你解除这个,这应该给你一个int*。也就是,0x4df73c是地址的地址,*pointer已经让你成为第二个地址。然后,通过添加(offset/sizeof(int))来执行指针运算,该运算结果为int*,其中计算出offset字节有多少个int。因此,当您添加此值时,您的int*将沿着该偏移点移动以指向int。你然后返回这个int*,一切都很好。

在第二个示例中,您将0x4df73c作为int*传递。然后您将其解除引用,这会给您一个int。现在+不做指针算术 - 它做整数算术。 (offset/sizeof(int))仍然会给你的int秒的offset字节数,但算术不会做你想要的。它不会将int的价值增加适当的金额。

比方说int在你的机器上是4个字节。当你有一个叫做pint*,而你做了p + 5时,这不仅仅是将5加到p的地址中。它增加了5倍大小的int(20字节),所以它现在指向第5个int。但是,如果您有一个叫做iint,而您的确做了i + 5,这确实只是增加了5

这就是你的问题。当你添加到int,你没有做适当的算术。我想这会,如果你将其更改为,假设int*int您的系统中相同的尺寸(如你说他们是)工作:

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

但我不推荐这种。不要使用int就好像它是一个指针。对(int*)的演员涉及reinterpret_cast,这很可怕。坚持你的第一个代码。

+0

为什么reinterpret_cast除了第二个版本对于试图阅读代码的人更迷惑/神秘的事实之外还有什么不好? – user2327287 2013-04-27 20:06:48

+0

@ user2327287这很糟糕,因为该标准的许多行为都未定义。用'reinterpret_cast'完成的唯一明确定义的事情是从'T *'转换为其他'U *',然后返回到'T *',并保证它仍然有效。其他一切都离开了理性的境界。你基本上认为将int解释为int *是一件好事,通常情况并非如此。 – 2013-04-27 20:08:50

+0

Interpert'int **'作为'int *'同样不好吗? – user2327287 2013-04-27 20:13:18

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)