首先,事實證明你已經打印的地址並不意味着在該地址被分配內存。您只需添加數字並生成其他數字。
其次,你通過加2得到的數字的原因是比基地址大8,而不是比基地址大2,這是因爲,當你在C中增加指針的整數時,算法是根據指向元素,而不是內存中的字節(除非指向的元素是字節)。假設你有一個int數組,例如int x[8]
,並且你有一個指向x[3]
的指針。向該指針添加兩個會生成一個指向x[5]
的指針,而不是指向x[3]
開頭以外的兩個字節的指針。記住C是抽象是很重要的,C標準指定了抽象內部發生的事情。在C抽象內部,指針運算對元素的數量起作用,而不是原始內存地址。 C實現(編譯器和將C代碼轉化爲程序執行的工具)需要對原始內存地址執行任何操作,以便實現由C標準指定的抽象。通常,這意味着編譯器在將元素添加到指針時將整數乘以元素的大小。所以兩個乘以四(在一臺機器上,其中int
是四個字節),並且八個結果被添加到基地址。
三,你不能依賴這種行爲。 C標準只針對指向數組內對象的指針定義指針運算,包括數組末尾的一個虛構對象。另外,指向單個對象的指針就像一個元素的數組一樣。因此,如果您有一個指向p
的指向int的指針,則允許您計算p+0
或p+1
,因爲它們指向數組中唯一的對象(p+0
),而虛擬對象指向數組中最後一個元素之外的一個對象(p+1
)。你是而不是允許計算p-1
或p+2
,因爲這些都在數組之外。請注意,這不是取消引用指針(嘗試讀取或寫入計算出的地址處的內存)的問題:即使僅僅計算,該地址也會導致C標準未定義的行爲:您的程序可能會崩潰,它可能會崩潰給你「正確」的結果,或者它可以刪除你帳戶中的所有文件,所有這些行爲都符合C標準。
單純計算出界限地址不會產生這種奇怪的行爲。但是,該標準允許它,因爲一些計算機處理器具有不尋常的地址方案,這需要比簡單算術更多的工作。也許在平坦地址空間之後的第二常用地址方案是基地址和偏移方案。在這種方案中,四字節指針的高16位可能包含基地址,低16位可能包含偏移量。對於給定的基地址b和偏移量o,相應的虛擬地址可能是4096 * b + o。 (這種方案僅能夠尋址字節,許多不同的基址和偏移值可以指相同的地址,例如,基址0和偏移量4096是指與基址1和偏移量0相同的地址。 )使用base-and-offset方案時,編譯器可以通過僅添加到偏移量並忽略基數來實現指針算術。 (這樣的C實現可以支持高達65536字節的數組,只能通過偏移量尋址的範圍)。在這種實現中,如果您有指向int p
且編碼爲0x0000fffc(基址0,偏移量65532)的指針,並且int
是四個字節,則p+2
將具有值0x00000004,而不是八個更大的值(0x00010004)。
這是一個例子,其中指針算術產生的值不會在平地址機器上產生。很難想象一個實現,其中根據C標準無效的指針運算會導致崩潰。但是,考慮一個實現,必須由進程手動交換內存,因爲處理器沒有硬件來支持虛擬內存。在這種實現中,指針可能包含內存中用於描述磁盤位置和用於管理內存交換的其他信息的結構地址。在這樣的實現中,執行指針運算可能需要讀取內存中的結構,因此執行無效指針運算可能會讀取無效地址。
在C中,你永遠不會通過像這樣的測試獲得很遠的學習;由於*未定義的行爲*你會發現很多不一致 - 你都不應該指望它們。 – Dave 2012-07-31 05:05:51
請首先使用SO搜索工具:[我可以使用更多的內存,而不是使用malloc()分配多少內存,爲什麼?](http://stackoverflow.com/questions/3509714/i-can-使用多內存而不是使用多少分配與malloc-why) – 2012-07-31 09:56:53