当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?
我一直在寻找,但找不到明确的答案.
很多人说使用工会来打字 - 双关语是不明确的和不好的做法.为什么是这样?考虑到你写入原始信息的内存并不仅仅是自己的改变,我看不出为什么它会做任何未定义的任何原因(除非它超出了堆栈的范围,但这不是一个联合问题,这将是糟糕的设计).
人们引用严格的别名规则,但在我看来,就像说你不能这样做,因为你做不到.
如果不打双关语,联盟的意义又是什么呢?我在某个地方看到它们应该被用来在不同的时间使用相同的内存位置来获取不同的信息,但为什么不在再次使用之前删除信息呢?
总结一下:
额外信息:我主要使用的是C++,但想了解它和C.特别是我正在使用工会在浮点数和原始十六进制之间进行转换以通过CAN总线发送.
这只是为了满足我自己的好奇心.
是否有这样的实现:
float InvSqrt (float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f3759df - (i>>1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
return x;
}
Run Code Online (Sandbox Code Playgroud)
在C#?如果存在,请发布代码.
我想我应该提到我正在寻找一个"安全"的实现......无论哪种方式,BitConverter代码解决了这个问题.工会的想法很有趣.我会测试它并发布我的结果.
编辑:正如预期的那样,不安全的方法是最快的,然后使用union(在函数内),然后是BitConverter.这些函数执行了10000000次,我使用System.Diagnostics.Stopwatch类进行计时.计算结果显示在括号中.
Input: 79.67
BitConverter Method: 00:00:01.2809018 (0.1120187)
Union Method: 00:00:00.6838758 (0.1120187)
Unsafe Method: 00:00:00.3376401 (0.1120187)
Run Code Online (Sandbox Code Playgroud)
为了完整性,我测试了内置的Math.Pow方法和"天真"方法(1/Sqrt(x)).
Math.Pow(x, -0.5): 00:00:01.7133228 (0.112034710535584)
1 / Math.Sqrt(x): 00:00:00.3757084 (0.1120347)
Run Code Online (Sandbox Code Playgroud)
1/Math.Sqrt()之间的差异是如此之小,以至于我认为不需要在C#(或任何其他不安全的方法)中使用不安全的快速InvSqrt()方法.除非真的需要从CPU中挤出最后一点果汁...... 1/Math.Sqrt()也更准确.
sqrt()关于GCC的math.h 标准的好奇心.我sqrt()使用Newton-Raphson 编写了自己的代码!