天天看點

指針的一些問題

1、c++/c語言中不少地方,數組和指針可以互相替換使用,容易讓人産生一種錯覺,指針和數組是等價的。

數組要麼在靜态存儲區域建立,如全局數組;要麼在棧上建立如函數内的數組。數組的名稱對應着(而不是指向)一塊記憶體,它的位址和容量在其生命周期内保持不變,數組的内容可變。

指針可以指向任意類型的記憶體塊,它的特征是可變的,是以常常用指針來操作動态記憶體,指針比數組靈活,當時容易出錯。

如上邊一段代碼,a是容量為6的字元數組,a中的内容是可以改變的,如a[0]='x'。指針p指向的是一個常量字元串“world”(位于靜态存儲區),常量字元串的内容是不能夠被修改的。但是從文法的角度看,編譯器并不知道p[0]='x'有什麼問題,但是該語句在企圖執行時,就會出錯。

<a></a>

另外指針和數組的容量計算也是有差別的。以上一段代碼為例,sizeof(a)的值為6,但是sizeof(p)的值為4,這是因為sizeof(a)可以計算出數組的位元組數,但是sizeof(p)得到的是一個指針變量的位元組數,相當于sizeof(char *),而不是p所指向的記憶體容量。c++、c語言是沒有辦法知道指針所指向的記憶體容量,除非在申請記憶體時記住。

注意:當數組作為函數的參數進行傳遞時,該數組自動退化為同類型的指針。如上邊的代碼,sizeof(p)的大小為4。

2、指針參數傳遞記憶體

這段代碼運作出錯,原因出自函數Getmemory中。編譯器總是要為函數的每個參數制作臨時副本,指針參數p的副本是_p,編譯器使_p=p。如果函數體内的程式修改了_p的内容,就導緻了參數p的内容作相應的修改。這就是指針可以用作輸出參數的原因。但是在本例中,_p申請了新的記憶體,隻是把_p所指向的記憶體位址改變了,但是p絲毫未變。是以函數GetMemory并不能輸出任何東西,每次執行一次GetMemory就會洩露一塊記憶體。因為沒有執行free釋放記憶體。

如果一定要使用指針參數去申請記憶體,那麼可以使用指向指針的指針,如上邊的代碼。當然也可以使用函數傳回值來傳遞動态記憶體,如:

但是值得注意的是,我們這裡使用傳回值傳回的是動态配置設定的堆記憶體,不是棧記憶體,如果不小心傳回的是棧記憶體,就會出錯,因為在函數結束時,棧記憶體自動消亡了。

對上邊的程式稍作修改

這時候p指向的是字元串常量,位于靜态存儲區,生命周期恒定不變,那麼此時傳回的是一個隻讀的記憶體塊。

3、結構體的存儲配置設定

如上邊所示兩個結構體的資料元素一樣,但是位置順序不同,那麼他們占用的記憶體大小不同。在32位機器中整型4個位元組,并且他的起始存儲位置必須能夠被4整除。是以以上兩個結構體在記憶體中配置設定如圖所示

指針的一些問題
指針的一些問題

編譯器按照成員清單的順序一個接着一個的給每個成員配置設定記憶體。隻有當成員之間滿足正确的對齊要求時,成員之間才會出現用于填充的額外記憶體空間。有些時候,我們有充分的理由決定不對資料結構成員進行重排,減少因邊界對齊帶來的空間損失。例如,我們可能想把相關的結構成員存儲到一起,提高程式的可維護性和可讀性。但是,如果不存在這樣的理由,結構成員應該根據他們的邊界進行重排,減少因為邊界對齊而造成的記憶體損失。當程式建立幾百個甚至上千個結構時,減少記憶體浪費的要求就比程式的可讀性更為緊迫了。在這種情況下,在聲明中增加注釋可以彌補可讀性方面的損失。

運作結果:

指針的一些問題

本文轉自NewPanderKing51CTO部落格,原文連結: http://www.cnblogs.com/newpanderking/p/3825417.html,如需轉載請自行聯系原作者