2011-04-09 352 views
1

試圖更好地學習指針數學我寫了這段代碼。其目的是增加指針投擲結構和打印它的成員。我知道如何打印成員更簡單的方法,但真的想知道我的指針數學是如何搞砸的。謝謝。C指針數學結構

typedef struct{ 
    int num; 
    int num2; 
    char *string; 
} astruct ; 

int main (int argc, const char * argv[]) 
{ 
    astruct mystruct = { 1234, 4567,"aaaaaaa"}; 

    astruct *address; 
    address = &mystruct; 

    // this does print 1234 
    printf("address 0x%x has value of:%i\n",address, *address); 
    address = address + sizeof(int); 

    //this does NOT print 4567 
    printf("address 0x%x has value of:%i\n",address, *address); 
    address = address + sizeof(int); 

    //this crashes the program, I wanted to print aaaaaaaa 
    printf("address 0x%x has value of:%s\n",address, **address); 

    return 0; 
} 

回答

5

指針算法通過指向的字節數遞增一個指針。例如,

int a[2]; 
int *p = a; 

assert(&a[0] == p) 
assert(&a[1] == p + 1) 

因此,你行

address = address + sizeof(int); 

實際上改變addressaddress + sizeof(int) * sizeof(astruct)(使用正常,沒有指針運算)。

由於允許編譯器在結構中引入填充,所以沒有保證的方式來執行所嘗試的操作。考慮結構

struct A { 
    char a; 
    int b; 
}; 

編譯器將最有可能給這個結構佈局如下:

+------------+-------------------+-------------+ 
| a (1 byte) | (3 bytes padding) | b (4 bytes) | 
+------------+-------------------+-------------+ 

所以你不能採取一個結構實例的地址,並添加1

得到 b

在你的特定的情況下,編譯器可能是沒有引入填充,所以你可以用這些行來更新address

address = (char *) address + sizeof(int); // OR... 
address = (int *) address + 1; 

此外,雖然,這完全取決於編譯器佈局的結構,你覺得會的方式,任何微小的變化可能會打破它,所以你真的不應該依賴於這種類型的行爲。

+0

並不能保證這兩個整數至少是連續的嗎? – Alnitak 2011-04-09 15:12:31

+0

該標準使得關於填充的mo保證。 (這就是所有*可能* s的原因) – hugomg 2011-04-09 19:22:10

3

添加到指針時,實際上會添加n * sizeof(*ptr)字節。

因此,在你的結構需要12個字節的32位機器上,添加sizeof(int)字節實際上會將48個字節添加到指針。

要在num2點,你必須先投地址的指針整數

int *iaddress = (int *)address; 

,然後添加一個,要達到你的4567值。

0

該結構旨在避免這種類型的計算。您可以使用mystruct.num,mystruct.num2mystruct.string來代替迭代內存。因爲你不爲'aaaaaaa'分配內存,所以這仍然是段錯誤。