簡體   English   中英

C:兩個void指針的區別是什么?

[英]C: what type is the difference of two void pointers?

如果我減去兩個空指針,我將得到兩個指針位置之間的相對距離(以字節為單位)(至少在我的測試系統上)。 我應該使用哪種類型來存儲結果,以使其與64位系統兼容? size_t是正確的類型還是長的?

背景:我們需要檢查給定的void指針用作雙指針是否安全。 我們曾經將指針強制轉換為int並檢查低三位是否為零,但是我們目前的編碼標准不再允許將指針強制轉換為整數類型。 我正在考慮計算void指針和NULL指針之間的差異,並檢查該差異是否可被8除。假設NULL指針始終是8字節對齊的?

空指針的減法未在C標准中定義。 僅當指針都指向同一個數組並且void指針不能指向任何數組時才定義指針減法,因為您不能擁有包含void元素的數組。

很可能您正在使用gcc或兼容的東西,並且它允許對void指針進行算術運算,並將其作為char指針的擴展。 但是嚴格的C編譯器不應允許對void指針進行指針運算。

C11, 6.5.6 Additive operators /9 (我的斜體):

當減去兩個指針時,兩個指針都將指向同一數組對象的元素,或者指向數組對象的最后一個元素之后的元素; 結果是兩個數組元素的下標不同。 結果的大小是實現定義的, 其類型(帶符號整數類型)是<stddef.h>標頭中定義的ptrdiff_t

在該部分中,從指針中減去NULL在技術上也是未定義的行為,因為絕對不能將NULL視為指向同一數組或該數組之外元素的指針。 指針減法實際上僅限於獲得同一數組中兩個元素之間的索引差。

因此,您可能想重新考慮一下您正在執行的檢查,尤其是考慮到雙精度實際上不需要八字節長的事實,即使是這樣,標准中也沒有要求將其對齊一個八字節的邊界。

我更傾向於只是在函數的文檔中指出,傳遞的值必須是有效的double指針,並且,如果函數的用戶違反了該合同,則所有押注均無效。

如果我減去兩個空指針,我將得到兩個指針位置之間的相對距離(以字節為單位)(至少在我的測試系統上)。

有一個嚴格的規則減去兩個指針。 C11-§6.5.6:

當減去兩個指針時,兩個指針都將指向同一數組對象的元素,或者指向數組對象的最后一個元素之后的元素; 結果是兩個數組元素的下標不同。 [...]


兩個void指針的區別是什么類型?

應該是ptrdiff_t

[...]結果的大小是實現定義的,其類型(有符號整數類型)是在<stddef.h>標頭中定義的ptrdiff_t [...]

問題摘要:

  • 您正在將空指針常量宏NULL與空指針混淆。 那是兩個不同的術語。 NULL宏始終等於0,但是空指針可以具有任何值。 看到這個

  • 話雖如此,使用空指針或NULL宏進行指針算術沒有任何意義。 這樣做會調用未定義的行為,因為指針必須指向同一數組。 請參閱paxdiablo的答案。

  • 此外,如Art的答案所述,您不能對void指針進行任何形式的算術運算。 +和-運算符指定為(6.5.6):

    另外,兩個操作數都應具有算術類型,或者一個操作數應是指向完整對象類型的指針,另一個操作數應具有整數類型。

    空指針是指向不完整類型的指針,因此,如果一個或兩個操作數都是空指針,則您的代碼無效C。

    請注意,GCC具有非標准擴展名,允許通過將空指針視為此類情況的字節指針來進行空指針算術運算。 如果要編寫安全且可移植的程序,請不要使用此非標准功能。 如果希望GCC充當標准C編譯器(符合實現),則使用gcc -std=c11 -pedantic-errors進行編譯。

暫無
暫無

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

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