簡體   English   中英

取消引用指針廣播變量的地址

[英]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轉換為整數。 如果temp1.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.

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