[英]Dereferencing the address of a pointer-casted variable
我發現這段代碼被截斷在一個更大的項目中,這確實讓我思考。
float sift_handler(int rs2, int rs4, int rs5);
int result1;
float temp = sift_hander(rs2, rs4, rs5);
result1 = *(int*)&temp;
據我了解,float temp
的地址被強制轉換為int指針,然后取消引用。 當我編譯這段代碼時,我得到一個警告
warning: dereferencing type-punned pointer will break strict-aliasing rules
針對result1 = temp
的實際好處是什么? 另外,使用round()
而不是僅進行強制轉換更好嗎?
針對result1 = temp的實際好處是什么?
它們是完全不同的操作。 result1 = temp
將值從float轉換為整數。 如果temp
為1.0f
,則result1
將為1
。 如果默認的舍入樣式(只是截斷)不令人滿意,則可以在分配給整數之前使用round()
。
另一方面, *(int*)&temp
重新解釋 float
變量的位,並將這些位存儲為整數變量。 1.0f
可能會導致一些巨大的整數值。 這稱為type punning 。
正如編譯器告訴您的那樣,使用無效類型的指針進行這種取消引用是嚴格的別名沖突 。 進行這種類型的校正的正確方法是:
memcpy(&result, &temp, sizeof temp);
過去,訪問浮點數表示法是一種古老的技巧。 這意味着它不是強制轉換,並且(如果未被UB捕獲)將給出不同的結果,但在通用實現中為0。
至少從C99和C ++ 11(對於以前的版本不確定)開始,這樣做會調用未定義行為,因為它違反了嚴格的別名規則。 發明該規則是為了幫助編譯器優化,方法是聲明只能通過自己的類型或字符類型來訪問變量。 這樣,當編譯器將浮點數存儲在寄存器中時,可以假定該浮點數不會因任何整數更改而被更改(非常簡單的解釋)。
但是,由於以前在較舊的程序中大量使用它,因此大多數編譯器(甚至是最近的編譯器)都可以選擇忽略嚴格的別名規則。
在這里,您的編譯器只是警告您此代碼違反了嚴格的別名規則,在某些實現上可能會導致UB。
TL / DR:使用強制轉換的指針訪問其他類型是嘗試重新解釋基礎表示形式,並且在C和C ++上均為UB。 絕對和演員不同。
針對result1 = temp的實際好處是什么
它所做的事情完全不同,並且不會將浮點數轉換為整數。 因此,根本不要使用指針修剪,直到您對指針,數據類型,其在特定實現中的表示等有所了解為止
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.