2009-12-13 93 views
2

我知道,指針包含的變量的地址,例如:這個C代碼錯了嗎?

int c = 5; 
int *p; 
p = &c; 
printf("%d",*p); // Outputs 5. 

但是,如果我想的地址發送給一個函數是什麼:

void function (int *p) 
{ 
    p++; 
} 
int c; 
function (&c); 

當函數被調用時的值&c被分配給int *p。我想確切的說明是:*p = &c;,但我不明白這是什麼意思。

回答

4

我更喜歡寫int* p = &c;,也就是說,指向int類型的指針被分配了c的地址。

指針符號可能會造成混淆,因爲你已經注意到了,因爲這兩個是相同的:

int *p = &c; 

int *p; 
p = &c; 

希望這有助於!

編輯:混亂是因爲*既用作解除引用運算符,也用於聲明指針。因此,當p包含地址c時,*p將指針取消引用並返回值c。但是當你說int *p = &c;時,*說「p是指向int的指針」,但是沒有進行任何解引用。

2

您確定p++;是您的意思嗎?這會增加p指向的位置,但不會遞增當前位置的值。如果你想增加價值(即使c變成6),那麼你想要的是(*p)++;

+0

不,它不會「增加p指向的位置」,它只是增加p。 – 2009-12-13 13:07:07

+0

對不起,我的部分表達不好。由於'p'是一個指針,所以遞增它會調用指針算術,這會將指針有效指向的內存地址移動一個點(改變*位置*,而不是*位置處的值* - 這就是我的意思通過遞增位置,而不是遞增位置處的值)。 – Amber 2009-12-13 13:10:37

3

如果你想要的功能,以增加c&c調用,那麼這樣寫:

void function(int *p) { ++(*p); } 

function(int *p)意味着p是函數的參數。因此,無論呼叫者給出的值如何,都將分配給p(而不是*p)。

p的類型是int *。也就是說,p是一個指向int的指針。

如果p是一個指向int的指針,那麼*p是它指向的int。

c是一個int。因此&c是一個指向int的指針,它指向的int是c。因此,如果p&c,則*pc

隨着我的版本的功能,此代碼:

int c = 5; 
function(&c); 

是否與此相同的代碼:

int c = 5; // same as before 
int *p; // parameter of the function 
p = &c; // assign the caller's value to the parameter 
++(*p); // body of the function, increments *p, which is the same as c. 

這確實與此相同的代碼:

int c = 5; 
++c; 
+0

非常感謝很多人,這正是我所要求的 – hamza 2009-12-15 17:30:19

3

我無法真正弄清楚你的問題,但function看起來像我的錯誤,你的意思是我s,或許,

++(*p) 

否則它是一個沒有操作。

+0

嚴格地說,該函數中的'p ++'調用未定義的行爲(因爲遞增p會創建一個指向無效位置的指針)。實際上,在所有普通的C編譯器中,它什麼都不做。 – 2009-12-13 14:40:10

+0

不,沒有未定義的行爲,因爲遞增的p永遠不會使它脫離函數並立即被丟棄。 – 2009-12-13 14:47:43

+0

但是即使計算這樣一個指針也是未定義的行爲,不是嗎? – 2009-12-13 15:31:52

4

*p = &c;指:

獲取其在 編譯時決定 鏈接時(感謝Mikeage)e.g,0x1234的作爲例子的c在存儲器中的地址。類型爲int的指針,即*p被分配給0x1234,這聽起來不合我的意思,我認爲你應該這樣做,p = &c然後*p將有值指向的地址c。因此*p將具有c分配給的值(這被稱爲解引用-通過在指針變量之前放置*然後您可以獲得該值)。

在你的函數中,你試圖增加p指向的值。

 
void function (int *p) 
{ 
    *p++; 
} 

// It would be called like this 
int c = 5; 
function(&c); // Now c would have 6! 

關鍵的一點是要通過引用傳遞這是什麼參數&c一樣。 如果省略引用傳遞這樣的:

 
void function (int p) 
{ 
    p++; 
} 
// And call it like this 
int c = 5; 
function(c); // c is still 5 

現在c仍然是5,但功能本身c是6,但沒有副本傳遞迴了,因爲它是在本地棧內增加內函數本身。

+0

迂腐,它只在編譯時部分確定;取決於所得到的對象的操作系統和/或共享文庫[我知道這不是一個短語],它可能是可重定位的。但你仍然得到一個+1爲使用提問者的正確水平的細節(我當然沒有......) – Mikeage 2009-12-13 13:35:17

+0

@Mikeage:謝謝:)那麼,在編譯時發生在連接權之前? ;)你就在那裏......也許這個詞應該是'在鏈接時',而不是編譯時......感謝指出它! :) – t0mm13b 2009-12-13 13:43:50

+0

實際上,在加載時間;有些情況下,它可以在運行時重新定位 – Mikeage 2009-12-15 09:29:19

1

其他人已回答你的問題。我將補充一點,閱讀指針聲明的有用方法是這樣的。假設我有以下聲明:

int i; 

這真的很容易。這裏,iint。現在,讓我們說我有這樣的:

int *pi; 

在這裏,你可以說pi是一個指向int(這是正確的)。另一種看待它的方式是*piint,即當你的代碼中有*pi時,*pi將是int類型。在瞭解之後,我認爲很容易看出++pipi++不會增加int,因爲pi是錯誤的類型。你想要(*pi)++。括號是必需的,因爲在C中,運算符++比一元運算符*具有更高的優先級。既然你不使用任何增量的副作用,你也可以這樣做:++*p

當然,就像所有的指針一樣,pi必須指出一些對上述有用的東西是有意義的。