2016-10-22 101 views
0

我對手動指定了帶偏移量的指針的整數值,看起來ptr+1實際上並不指向second_int,或者是因爲printf函數不知道大小的ptr+1將偏移值賦值給指針C

#include <stdio.h> 

int main(void) 
{ 
    int first_int = 42; 
    int second_int = 23; 

    int *ptr = &first_int; 
    *(ptr + 1) = second_int; 

    int i = 0; 
    for (i = 0; i < 2; i++) { 
     printf("%d\n", *(ptr+i)); 
    } 

    return 0; 
} 

,輸出是:

42 
1

難道不應該是42和23?

而且我發現每次我打印*(ptr+1)時,它遞增1

#include <stdio.h> 

int main(void) 
{ 
    int first_int = 42; 
    int second_int = 23; 

    int *ptr = &first_int; 
    *(ptr + 1) = second_int; 

    int i = 0; 
    for (i = 0; i < 10; i++) { 
     printf("%d\n", *(ptr+1)); 
    } 

    return 0; 
} 

,輸出是:

0 
1 
2 
3 
4 
5 
6 
7 
8 
9 

發生了什麼?

編輯:
我只允許使用指針,但並非陣列(做學習C堅硬方式鍛鍊; Tibial)。所以我通過int *ptr = malloc(sizeof(int) * 2);手動爲ptr分配內存,然後我給ptrptr + 1賦值,並且代碼按預期運行。

+3

未定義的行爲發生。 second_int不保證與first_int相關的特定位置,更不用說您期望的。你已經踐踏了記憶中的其他地方,我猜想它屬於變量「i」。 –

+1

你爲什麼認爲ptr + 1指向second_int? – immibis

回答

0

在您的代碼中,ptr+1不是由您管理的內存。
它可以被其他程序或任何零件或程序使用。這裏發生的事情是編譯器優化了second_int,因爲只使用它的值。所以沒有內存分配給它。
幸運的是,內存中的下一個int也由您管理,並且它是您的循環的索引。
你以爲內存佈局是這樣的:
first_int | second_int | i

但它是像這樣:
first_int | i

如果你希望能夠指既詮釋了指針+偏移,那麼你必須聲明爲一個數組,以確保它們是連續存儲:
int my_ints[2] = { 42, 0};
int *ptr = my_ints;
*(ptr+1) = second_int;
然後你的代碼將按預期工作。

+0

非常感謝,學到了很多! – xawyzen

2

當您有一個指向單個值的指針時,您只能取消引用它以訪問該特定值,而不是其他值。爲了能夠增加一個指針,它必須指向數組內的一個對象。

E.g.這將是有效的:

int integers[2]; 
int *ptr = &integers[0]; 

*(ptr + 1) = 2; // Sets integers[1]. 

你似乎想設置*(ptr + 1)second_int點。在C語言中,唯一可以指向單個值變量的方法是使用地址運算符,即&second_int。但是該值的類型是int*,而不是int。我想,也許你想是這樣的:

int first_int = 42; 
int second_int = 23; 

int *array[2]; 
array[0] = &first_int; 
array[1] = &second_int; 
int **ptr = &array[0]; 

現在你可以使用**ptr*ptr[0]訪問first_int**(ptr + 1)*ptr[1]訪問second_int

+0

你確定你的意思是「遞減」而不是「解除引用」嗎? – EOF

+0

@EOF啊,謝謝。 –

+0

另外,你*被允許增加一個指向單個對象的指針。指針可能指向*數組或對象,您無法取消引用這樣的指針。 – EOF