簡體   English   中英

ptrdiff_t 的動機是什么?

[英]What is the motivation for ptrdiff_t?

為什么 C 為兩個指針之間的差異定義一個單獨的類型? 例如,為什么不能將其定義為long long ,甚至不能定義為intmax_t 是否有過intmax_t不等於ptrdiff_t的時候?

基本上,為什么這個 typedef(具有特定的字符串格式等)有用是什么意思? 作為一個基本的使用示例,我正在做:

int a = 1, b = 2;
printf("%td XXX\n", (char *)(&b) - (char *)(&a)); // 't' is formatter for prtdiff_t

是否有過intmax_t不等於ptrdiff_t的時候?

是的,在指針為 32 位且intmax_t >=64 位的 32 位平台上。

這是 C 標准中的相關段落:

6.5.6 加法運算符
[...]
語義
[...]
9.當兩個指針相減時,都指向同一個數組object的元素,或者數組object的最后一個元素; 結果是兩個數組元素的下標之差。 結果的大小是實現定義的,其類型(帶符號的 integer 類型)是在<stddef.h> header 中定義的ptrdiff_t 如果結果在該類型的 object 中不可表示,則行為未定義。 換句話說,如果表達式PQ分別指向數組 object 的第i個和第j個元素,則表達式(P)-(Q)的值是i - j ,前提是該值適合Ptrdiff_t 類型的ptrdiff_t 此外,如果表達式P指向數組 object 的元素或數組 object 的最后一個元素,並且表達式Q指向同一數組 object 的最后一個元素,則表達式((Q)+1)-(P)((Q)-(P))+1-((P)-((Q)+1))具有相同的值,並且如果表達式P指向超過數組 object 的最后一個元素,即使表達式(Q)+1不指向數組 object 的元素。 108)


108) 處理指針運算的另一種方法是首先將指針轉換為字符指針:在此方案中,在轉換后的指針中添加或減去的 integer 表達式首先乘以最初指向的 object 的大小, 並將結果指針轉換回原始類型。 對於指針減法,字符指針之間的差異結果同樣除以最初指向的 object 的大小。 以這種方式查看時,實現只需在 object 結束后提供一個額外字節(可能與程序中的另一個 object 重疊)以滿足“過去最后一個元素”的要求。

盡管 C 標准沒有強制要求,但ptrdiff_t通常定義為簽名的 integer 類型,大小與size_t相同。 On architectures where the maximum size of an object is limited to 32 bits, such as 32-bit Windows and Unix systems, size_t is an unsigned 32-bit integer type and ptrdiff_t a signed 32-bit integer type, whereas on 64-bit systems具有更大的地址空間,它們都是 64 位 integer 類型,對ptrdiff_t有符號,對size_t無符號。

但是請注意,兩個指針指向一個非常大的char數組的差異可能會超出與size_t大小相同的有符號類型的范圍。 例如,3GB char 數組可能在 32 位系統上可用( UINT32_MAX > 3GB),但 2 個指針的絕對值之差可以大到 3GB,這超出了int32_t的范圍,因此適合ptrdiff_t類型這個平台的,調用未定義的行為。

大多數實現通過減去地址並將結果除以元素大小來獲得差異,如果大小是 2 的冪,則使用有符號算術或有符號右移。對於大於char的大型 arrays 元素,這可能會產生不正確的結果,即使該值適合ptrdiff_t類型的 object 。

使用實現定義類型ptrdiff_t而不是long long的基本原理是保持與現有實現的兼容性,並避免在地址空間較小的系統上使用較大的類型,這會導致空間和時間的額外開銷。 在早期的 C 實現中,類型int用於此目的,並且當size_t引入的范圍可能與unsigned int不同時,由於int太小,因此需要用於 2 個指針差異的特定類型。 ptrdiff_t可能仍然太小,但僅適用於邊界情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM