既然在變數前加一個&就可以得到地址,為什麼還需要指針?


來理清一下思路吧。

我們通常說的指針,一般是指「指針類型」或「類型為指針的對象」。對於 T t; 來說,t 是一個右值表達式,它的類型是"指向類型為T的對象的指針」,而它的值是「t的地址」。

通俗地來說,指針(對象)是一個箱子,而地址是箱子里的東西,兩者並不矛盾。

至於「對象」,「右值」是什麼,這裡暫時就不展開了。


既然寫一個數字就能得到值,為什麼還需要變數?

----------------------------------------------------------

正經的,其實指針也是變數的一種,只不過存的是指向某個內容的內存地址。比如要實現一個鏈表結構,每個節點就可以用一個指針存儲它的後繼。假如刪除它的後一個元素,只要把這個指針指向後繼的後繼即可。這就體現了指針變數的靈活性。


C/C++ 里表達式全都是要有類型的。

變數前加一個 能得到地址,地址是此表達式的值,那表達式的類型是什麼?

指針類型丟掉,就無法表示此表達式的類型了……就憑這個理由也得留著指針啊。

(初看到這個問題時腦袋好像短路了一樣)


一切都是數據,地址也是數據,它的值還是個整型……

這麼一想的話好像是可以去掉指針。

比如intptr_t ptr = arg;

但是指針可不只是一個地址,它還暗藏了類型信息(所指向元素的大小)。

也就是說int*的指針++,地址值+4,char*的指針++,地址值+1。

光憑這一點,就不應該取消指針。


朋友 的確加就得到地址

但你拿一個地址沒有用啊

看看代碼裡面都是怎麼使用這個地址的

一元*操作

++操作

--操作

[]操作

指針 - 指針

這些使用指針的方法

都依賴於類型啊

int* 指針 進行++ 會前進一個int大小的內存

沒有int* 你對地址進行 ++ 什麼意思?

應該加多少? 按照加1處理? 多加幾次?

指針是地址這種說法毫無意義

寫代碼 很多時候 根本不關心地址

賦值操作 我要向內存某個地址寫入4個位元組的數據

這個地址是 0x12345678 還是 0x12345670

根本沒人在意


地址不能動(常量)

指針可以動(變數)


因為我們需要一個變數來保存地址啊


因為你要保存這個量啊

比如var a = b;

那麼這個var的類型,不能是int吧……只好用一個新的類型表示這個var。

pointer a = b

這樣的寫法是可行的,但是這樣編譯器就失去了推斷*a的類型的能力,這樣的話程序員就必須在所有用到*a的場合手動指定*a的類型,這樣就很可怕

所以就需要這樣的寫法

pointerof(T) a = b;//typeof(b) is T

而在C中確切的寫法是形如這樣的

T b, pointer a = b;

就變成了

T b, *a = b;

雖然更好的寫法是

T b;

T* a = b;


因為有對內存地址進行運算的需求


運算符得到的是地址常量,而指針是地址變數,所以為什麼要指針應該是個顯而易見的問題了吧?如果還不明白,那就問你有了1234,為什麼還要int變數


指針也是個數值 可以加加減減 用得到後 找個地方保存起來(指針) 方便日後對他ooxx


因為你需要一個東西來儲存這個地址

這個東西的類型名稱

叫指針,

名字不重要,

叫針指,指指,針針,也是ok的。

正如你需要一個東西來儲存數字2333

這個東西的類型名稱

叫int,叫long 叫short

名字不重要,

叫tni,tnt,nihen666,也是ok的。

關鍵是要一個東西來儲存你的數據,這個能方便你的操作。

當然你說這些類型不存在的,你不需要。

你只要一串數字就行。

也是沒有問題的

你用彙編來寫代碼。

但是你說不行,彙編還有基本數據類型

這個感覺有點多餘了啊,沒必要啊,給我一串數字就行。

00010101011000101011001010101010010101010110010101000101011001010101010101010101010101010101010101011100100001010101010101010101010


你都把地址取出來了,不存下來怎麼用


題主這個問題實在是提的太好了,直接切入到指針到底是什麼。很多答案其實都已經給出很好的解釋了。

指針實際上是一種類型,它本身理應是個形容詞,用來修飾名詞,比如說指針變數,指針函數等等。但我們平時習慣上有時候會省略變數這兩個字,使得指針變成一個名詞,比如說函數指針,其實說的是類型為指針的變數。

另外,指針這個名字起的就非常形象,一個指針變數宛如一個行蹤不定的游標,就如同你的滑鼠一樣,它表示的是內存上的一個地址,因為地址是整形的,所以可以通過對指針變數的加減操作獲得不同的地址。

而指針是否有存在的必要?那當然,因為你必須要通過一種類型來告訴編譯器你要定義一個東西,它不是整數也不是字元,而是一個游標,換句話說是一個地址變數,我希望可以通過它獲取該地址上的一個整數或者字元(所以你要在定義指針的同時加int、char之類的類型)。

理解了這個游標那接下來的事都簡單了,指針函數是因為它返回的函數值是一個指針,函數指針是因為你這個游標上想要讀取的東西是個函數而已…這些傻逼名詞就是繞舌頭,其實可以顧名思義的,就是有點花里胡哨罷了。

聽了以上這些題主應該就能明白指針是什麼了,但還有一個問題是,為什麼需要指針這種變數?原因很簡單,正是因為指針變數可以移動,你可以通過改變指針變數來訪問不同的內存地址以此獲得存儲的數據。它的的存在可以解決很多問題,比如說,你要寫一個可以交換兩個值的函數並可以得到交換過的值的這兩個變數,可是函數只能返回一個數值,怎麼辦?於是你就可以在函數參數里傳進去兩個游標,然後使得兩個游標交換位置不就行了。

另外有了指針,直接對內存操作使得計算機的處理速度非常快,這也是c語言至今仍是編程界的老大的主要原因。


舉個例子,有一個複雜的struct T

{

char msg[256][5];

......

};

比如我想列印msg的第二個元素,是這樣

T x;

...

printf("%s
", x.msg[0][1]);

因為不能用指針,所以寫成初始取地址

這樣呢,我們每次列印這個x元素msg的第二個元素時,都要來一遍x.msg[0][1],實際情況很多時候比這個還複雜,每次處理一個值就需要從根上一路點下去,這明顯不是個供人類使用的方式。

我們直觀的感受就是,那我做個變數等於這個值,每次需要的時候就用這個變數吧,那麼我們會寫成這樣

char[256] tmp;

strcpy(tmp[0],x.msg[0][1] );

因為tmp[0]這個東西是不能做左值的,所以需要寫成這樣

然後複製內容也是個大的性能槽點,為啥我不能直接用x里那個內容,而要複製一份,因為你寫不出來,沒有指針類型,這就寫不出我們希望的那個樣子。

可能有人會說用引用,

比如

char[256] tmp = x.msg[1];

但是很遺憾,引用是C++的內容,不是c的,其實引用不過是指針另外一種寫法。

如上,寫程序,需要指針類型,是個語言表達力的問題,是我們實際工作中確實需要的東西。


因為有時候你連這個變數都無法寫出來。最典型的就是鏈表。比如一個鏈表有三個節點,我要知道第二個節點的地址,你用哪個變數的地址來表示?


不是所有變數都是只有幾個位元組大,變數也可以是結構體,Windows API里很多結構體比如WNDCLASS、OPENFILENAME常常有幾十甚至上百位元組,如果結構體直接用作RegisterClass()、GetOpenFileName()的參數,會很費力,所以用指針代替。


不考慮重載的話,單目的取得的就是指針。


我就問你取了地址放哪?

指針就是用來保存地址的。

設type是類型,

type a;是個變數。

type *p;就是個指針。

指針是對象,用來保存地址用的。指針需要指向對象的類型是因為指針移動的時候需要知道移動多遠。

p = a;就是把a的地址放到p這個指針里。a作為地址放不下type型變數。因為地址也是個數據類型。

type*指向type類型。

類似的,將type*作為type則有

type**指向type*。以此類推。

當初C語言沒有引用傳遞,傳指針過去讓別的函數修改變數。

再說指針是個好東西。

沒有指針,我要你地址何用?

傳值?值很大(內存)咋辦?


變數a的地址a,沒有指針這個類型的話,那你告訴我,a+1是什麼


推薦閱讀:

有哪些語言可以做到:List<T> 實現介面 I(或繼承某個類)當且僅當 T 實現 I?
關於MSIL中的Nop的問題?
xamarin 怎麼發音?
快速開發桌面程序用什麼技術合適?
async/await非同步模型是否優於stackful coroutine模型?

TAG:C編程語言 | C | C# | CC | 指針 |