2013-04-27 20 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)