2017-02-24 176 views
1

我有以下代碼,使用C的指針涉及理解指針(在C):將INT字符指針和改變值

void 
f(void) 
{ 
    int a[4]; 
    int *b = malloc(16); 
    int *c; 
    int i; 

    printf("1: a = %p, b = %p, c = %p\n", a, b, c); 

    c = a; 
    for (i = 0; i < 4; i++) 
     a[i] = 100 + i; 

    c[0] = 200; 
    printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n", 
      a[0], a[1], a[2], a[3]); 

    c[1] = 300; 
    *(c + 2) = 301; 
    3[c] = 302; 
    printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n", 
      a[0], a[1], a[2], a[3]); 

    c = c + 1; 
    *c = 400; 
    printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n", 
      a[0], a[1], a[2], a[3]); 

    c = (int *) ((char *) c + 1); 

    *c = 500; 
    printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n", 
      a[0], a[1], a[2], a[3]); 

    b = (int *) a + 1; 
    c = (int *) ((char *) a + 1); 
    printf("6: a = %p, b = %p, c = %p\n", a, b, c); 
} 

int 
main(int ac, char **av) 
{ 
    f(); 
    return 0; 
} 

輸出:

1: a = 0x7fff5fbff710, b = 0x1003002e0, c = 0x100000000 
2: a[0] = 200, a[1] = 101, a[2] = 102, a[3] = 103 
3: a[0] = 200, a[1] = 300, a[2] = 301, a[3] = 302 
4: a[0] = 200, a[1] = 400, a[2] = 301, a[3] = 302 
5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302 
6: a = 0x7fff5fbff710, b = 0x7fff5fbff714, c = 0x7fff5fbff711 
Program ended with exit code: 0 

我明白爲什麼一個[1]是128144(當我們將int指針轉換爲char +1並覆蓋500時,我們正在向前移動一個字節),但我不明白爲什麼[2]是256 [[第一位會越過 - 寫,但不給256]。我將非常感謝幫助!感謝提前:)

+0

雖然它可能不是你的問題的原因在這裏,我強烈建議你閱讀嚴格的別名規則和未對齊的內存訪問 – bace1000

回答

0

實現的是,這

c = (int *) ((char *) c + 1); 

使得C地點一些的[1]和一些的[2]。您將c移過一個字節,並使其成爲一個int指針。這使得* c地址是[1]的最後3個字節和[2]的第一個字節。畫出所有位,看看會發生什麼

+0

我做的確實是它給出[1] = 128144(匹配)。 但是,[2]並不是256,你可以嘗試一下嗎? (我可以在我的結尾張貼它看起來像的圖像 - 如果有幫助,請告訴我) –

+0

這可能是未定義的行爲。 – Barmar

+0

安德魯爲我們完成了繁重的工作,並向您展示了這是如何發生的,我將它作爲一個練習題留給了您 – pm100

2

簡短回答:您修改了c,因此它不再具有4字節的整數對齊方式,並將其設置爲500個修改過的兩個數組元素。而且,這種未對齊的訪問通常是否定的,並且會在某些系統上導致對齊錯誤。

龍答:在步驟4,a[1]包含0x00000190這是400,和a[2]包含0x0000012D是301

假設a[0]開始在內存地址0這裏是個字節是如何排列的小-endian系統(字節順序是非常重要的在這裏),左到右從0到15:

ADDR: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
DATA: C8 00 00 00 90 01 00 00 2D 01 00 00 2E 01 00 00 

在步驟5您通過投已經對齊c一個字節一個char *,所以它指向一個地址05而不是04。您指定值500(0x000001F4)給它,這將覆蓋字節從05-08,造成這種記憶:

ADDR: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
DATA: C8 00 00 00 90 F4 01 00 00 01 00 00 2E 01 00 00 

當你讀到a[1]你0x0001F490這是128144.
當你讀到a[2]你得到0x00000100這是256.