gch*_*uel 44 c# unsafe type-punning
任何人都可以用简单的方式解释下面的代码:
public unsafe static float sample(){
int result = 154 + (153 << 8) + (25 << 16) + (64 << 24);
return *(float*)(&result); //don't know what for... please explain
}
Run Code Online (Sandbox Code Playgroud)
注意:上面的代码使用不安全的功能
对于上面的代码,我很难过,因为我不明白它的返回值与下面的返回值之间的区别是什么:
return (float)(result);
Run Code Online (Sandbox Code Playgroud)
如果你回来了,是否有必要使用不安全的功能*(float*)(&result)
?
Mar*_*age 75
在.NET上,使用32位存储float
的IEEE binary32单精度浮点数表示.显然,代码通过将位组合成a int
然后将其转换为float
using来构造此数字unsafe
.使用C++术语称为reinterpret_cast
强制转换,在执行强制转换时不进行转换 - 这些位只是作为新类型重新解释.
汇编的数字是4019999A
十六进制或01000000 00011001 10011001 10011010
二进制:
10000000
(或128),导致指数128-127 = 1(分数乘以2 ^ 1 = 2).00110011001100110011010
,如果没有别的话,几乎具有可识别的零和1的模式.返回的float与2.4转换为浮点的位完全相同,整个函数可以简单地用文字替换2.4f
.
最后的零那种"打破分数的位模式"可能是为了使浮点数匹配可以使用浮点文字写入的东西?
那么常规演员和这个奇怪的"不安全演员"之间的区别是什么?
假设以下代码:
int result = 0x4019999A // 1075419546
float normalCast = (float) result;
float unsafeCast = *(float*) &result; // Only possible in an unsafe context
Run Code Online (Sandbox Code Playgroud)
第一个1075419546
转换采用整数并将其转换为其浮点表示,例如1075419546f
.这涉及计算将原始整数表示为浮点数所需的符号,指数和分数位.这是一项必须完成的非平凡计算.
第二次演员阵容更加险恶(并且只能在不安全的环境中演出).的&result
需要的地址result
的指针返回到其中整数的位置1075419546
被存储.*
然后可以使用指针解引用运算符来检索指针指向的值.使用*&result
将检索存储在该位置的整数,但是首先将指针强制转换为(指向a float*
的指针float
)而是从内存位置检索浮点2.4f
,从而导致浮点被赋值unsafeCast
.所以叙述*(float*) &result
是给我一个指针,result
并假设指针是指向a的指针float
并检索指针指向的值.
与第一次投射相反,第二次投射不需要任何计算.它只是将存储的32位推result
入unsafeCast
(幸运的是也是32位).
一般来说,执行像这样的演员可能会在很多方面失败,但通过使用unsafe
你告诉编译器你知道你在做什么.
Bra*_*ith 18
如果我正在解释方法正确的做法,这是一个安全的等价物:
public static float sample() {
int result = 154 + (153 << 8) + (25 << 16) + (64 << 24);
byte[] data = BitConverter.GetBytes(result);
return BitConverter.ToSingle(data, 0);
}
Run Code Online (Sandbox Code Playgroud)
正如已经说过的那样,它正在重新解释这个int
价值float
.
归档时间: |
|
查看次数: |
2756 次 |
最近记录: |