当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?
John Carmack在Quake III源代码中有一个特殊的功能,它计算浮点的平方根,比常规的快4倍(float)(1.0/sqrt(x)),包括一个奇怪的0x5f3759df常量.请参阅下面的代码.有人可以逐行解释这里究竟发生了什么以及为什么这比常规实现快得多?
float Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y;
i = 0x5f3759df - ( i >> 1 );
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) );
#ifndef Q3_VM
#ifdef __linux__
assert( !isnan(y) );
#endif
#endif …Run Code Online (Sandbox Code Playgroud) 我正在开发一个项目来构建一个小编译器,只是为了它.
我决定采用构建一个非常简单的虚拟机来实现目标,所以我不必担心学习精灵,英特尔组装等的来龙去脉.
我的问题是关于使用工会在C中打字.我决定只在vm的内存中支持32位整数和32位浮点值.为方便起见,vm的"主内存"设置如下:
typedef union
{
int i;
float f;
}word;
memory = (word *)malloc(mem_size * sizeof(word));
Run Code Online (Sandbox Code Playgroud)
所以我可以根据指令将内存部分视为int或float.
这在技术上是打字吗?当然,如果我使用int作为内存的话,然后使用float*来像浮点数一样对待它们.我目前的方法虽然在语法上有所不同,但我认为它在语义上并不相同.最后,我仍然将内存中的32位视为int或float.
我在网上提出的唯一信息表明这是依赖于实现的.是否有更便携的方式来实现这一点而不浪费一大堆空间?
我可以做到以下几点,但接下来我会占用相当于工会的2倍以上的记忆和"重新发明轮子".
typedef struct
{
int i;
float f;
char is_int;
}
Run Code Online (Sandbox Code Playgroud)
编辑
我也许没有说清楚我的确切问题.我知道我可以使用一个没有未定义行为的联合中的float或int.我所追求的是一种具有32位内存位置的方法,我可以安全地将其用作int或float,而不知道最后一个值集是什么.我想说明使用其他类型的情况.