![](/img/trans.png)
[英]How does pointer comparison work in C? Is it ok to compare pointers that don't point to the same array?
[英]Why we can't compare pointers which don't point to elements within the same array?
我一直在學習C語言,並跟隨Yashavant P. Kanetkar的“Let Us C”。
指針章節中有一行說我們只能比較指向同一數組中元素的指針,即小於(<)和大於(>)指針。
為什么比較任意指針無效?
因為C沒有假設主機,並且沒有什么能阻止后者在兩個完全獨立的地址空間中分配兩個數組。
它不僅僅是關於理論上的異域架構 。 x86機器的16位編譯器提供了兩種指針。 近指針是16位寬,表現得像你期望的那樣; 但是,它們只允許您訪問64k的RAM。 如果你想訪問超過64k的RAM(每個塊不是64K:整個程序是64K!)你必須使用遠指針。
遠指針是32位寬,由兩個16位半部分組成,即segment
和offset
; 例如1234:0000
是一個具有段0x1234
和偏移0的指針。實際的存儲器地址是segment * 16 + offset
。 通常, farmalloc
返回一個零偏移量的指針,而指針算法僅修改偏移量。 所以你可以擁有
char *x = farmalloc(64); // returns 1234:0000 for address 0x12340
char *y = farmalloc(64); // returns 1238:0000 for address 0x12380
現在,如果計算x + 128
,則結果為1234:0080
,地址為0x123C0。 它比較less than
1238:0000(因為0x1234 <0x1238),但它指向更高的地址(因為0x123C0> 0x1238)。
為什么? 因為128到x
求和,它指向一個64字節的對象,是未定義的行為。
內存模型編譯器設置定義了指針的默認大小是近還是遠。 例如,“小”內存模型的代碼為64K,所有全局變量,自動變量(堆棧)和malloc堆的64K。 請注意,代碼位於一個單獨的段中,因此您不能只使用16位(“近”)函數指針並將其取消引用以讀取機器語言! 如果必須這樣做,則必須要求編譯器將代碼放在與其余代碼相同的段中(“微小”內存模型)。
一些內存模型讓編譯器總是使用遠指針,如果數據+堆棧+堆超過64K(“緊湊”或“大”內存模型),則速度較慢但是必需。
代碼和數據的大小也不同,所以你可以有一個內存模型,其中函數指針靠近但數據指針很遠,反之亦然。 前面提到的“緊湊”模型(64K代碼限制但遠程數據指針)和雙“中”模型(代碼的遠指針,64K數據限制)就屬於這種情況。
編譯器還有一種方法可以使用扁平的32位指針(所謂的“巨大的”內存模型),但它很慢並且沒有人使用它。
未定義的行為適用於此處。 你不能比較兩個指針,除非它們都指向同一個對象或指向該對象結束后的第一個元素。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.