2011-07-27 219 views
1

我發現我的bug(幾個小時後),並在下面的程序中將其隔離。問題在於當使用指向結構的指針時,計算pst2變量的值的方式。當使用指向char的指針時,一切正常。爲什麼是這樣?
(使用GCC /克++版本:(Debian的4.4.5-8)4.4.5)
(對於那些誰知道:我訪問以規則的偏移包含數據的分組的一個文件緩衝器)C++指針算術奇怪

#include <iostream> 
#include "testpa.h" 

#pragma pack(push) 
#pragma pack(1) 
//--------------------------- 
struct st_one 
{ 
    int i; 
    char c; 
}; 
//--------------------------- 
struct st_two 
{ 
    long l; 
    int i; 
}; 
#pragma pack(pop) 

//=========================== 
int main() 
{ 
    int n=1024, np1=sizeof(st_one); //, np2=sizeof(st_two); 
    st_one *pst1, *pst1a; 
    st_two *pst2, *pst2a; 
    char *pc1, *pc2, *pc1a, *pc2a, *pb; 

    pb = new char[n]; 

    pst1 = (st_one*)(pb); 
    pst2 = (st_two*)(pst1 + np1); //using pst1 
    pc1 = (char*)(pb); 
    pc2 = (char*)(pc1 + np1); //using pc1 

    pst1a = (st_one*)(pb); 
    pst2a = (st_two*)(pb + np1); //using pb 
    pc1a = (char*)(pb); 
    pc2a = (char*)(pb + np1); //using pb 

    std::cout << "\npb = " << (long)pb; 
    std::cout << "\n-----"; 
    std::cout << "\npst1 = " << (long)pst1 << "\tpst2 = " << (long)pst2; 
    std::cout << "\npc1 = " << (long)pc1 << "\tpc2 = " << (long)pc2; 
    std::cout << "\n-----"; 
    std::cout << "\npst1a = " << (long)pst1a << "\tpst2a = " << (long)pst2a; 
    std::cout << "\npc1a = " << (long)pc1a << "\tpc2a = " << (long)pc2a; 
    std::cout << "\n-----\n"; 

    return 0; 
} 

輸出:

pb = 19546128 

pst1 = 19546128   pst2 = 19546153 <--- WRONG! 
pc1 = 19546128   pc2 = 19546133 

pst1a = 19546128  pst2a = 19546133 
pc1a = 19546128  pc2a = 19546133 
+0

我不明白這是怎麼回事。你期待什麼行爲? –

+0

這是困難的方式。 'pst1 [offset] .c'有什麼問題?讓編譯器完成這項工作,它將會執行指針運算,並且不會比你更容易出錯。 – msw

回答

8

這看起來好像沒什麼問題。行:

(pst1 + np1) 

在增加的st_onenp1實例什麼pst1點,這意味着pst1價值由np1 * sizeof (st_one)字節,這是25遞增(的sizeof = 5),其對應於你已經值輸出。取而代之的是上面的,我想你想:

(pst1 + 1) 

pc1值工作,因爲這是一個char指針,所以該行:

(pc1 + np1) 

增加np1 * sizeof (char)字節pc1,這是5個字節。

遞增指針會使指針指向內存中的下一個元素,而不是下一個字節。

+0

我總是覺得在任何外部操作完成之前,括號內的值會先計算出來。在這種情況下,我會認爲pst1和np1的整數值會在作爲指針投入之前被添加。 – slashmais

+0

啊!我強調了我犯了我的錯誤 - 謝謝。 – slashmais

3

您不應該添加sizeof(x),因爲這是自動完成的。當您增加一個指針時,如++ p,地址會增加對象的大小,以便它指向下一個。

將1添加到指針與++ p相同。添加sizeof(x)將增量縮放兩次。

你的計算工作的優良字符,因爲的sizeof(char)的爲1

1

它看起來像你得到的一切是錯誤的。例如,從PST1 GET PST2,你有一個遞增它,因爲指針pst1st_one *型的,所以你必須這樣寫:

pst2 = (st_two*)(pst1 + 1);

..但是你必須:

pst2 = (st_two*)(pst1 + np1);

...其中NP1是st_one一個sizeof,所以它會跳過許多st_one結構作爲結構具有字節...

閱讀有關指針運算的一些文檔,如this one

+0

好的,會閱讀 - 謝謝。 – slashmais

2

C++會自動將您要添加的整數乘以指針指向的元素的大小。它假定你想通過整個元素而不是字節來提前指針。

2

C和C++中的指針運算是指針指向的類型的sizeof。也就是,int *abc = /* ... */; int *def = abc + 1結果def結果int提前abc,而不是char

至於你將指針轉換爲long s,這是實現定義的行爲,所以你可能會在不同的機器上得到奇怪的結果。 (對於這個問題,在指針類型之間也是如此)C++說那也是實現的定義)