C语言 内联浮点到uint“表示”类型双关不工作?

j13ufse2  于 2023-04-29  发布在  其他
关注(0)|答案(3)|浏览(126)

这是在C中,但我标记为C++,以防它是相同的。这是建立与:Microsoft(R)32位C/C++优化编译器版本14。00.50727.220(80 x86),如果有任何不同
为什么会这样?
(inVal是0x 80)

float flt = (float) inVal;
outVal = *((unsigned long*)&flt);

(结果outVal为0x 43000000--正确)
但这不是吗

outVal = *((unsigned long*)&((float)inVal));

(导致outVal为0x 00000080-- NOT CORRECT:()
在问这个问题之前,我在谷歌上搜索了一下,发现这个java函数基本上是我想要的。如果你对我想做的事情有点困惑,这个程序可能有助于解释:

class hello
{
    public static void main(String[] args)
    {
        int inside = Float.floatToIntBits(128.0f);
        System.out.printf("0x%08X", inside);
    }
}
p1iqtdky

p1iqtdky1#

你试图获取一个非常量临时变量的地址(你的(float)转换的结果)--这在C++中是非法的(可能在C中也是如此)。因此,您的代码会导致垃圾。
在你的第一个工作代码中,你没有使用临时的,所以你的代码是工作的。请注意,从标准的Angular 来看,这仍然是定义不清的,因为所涉及类型的大小和内部表示没有指定,并且可能因平台和编译器而异。不过,你应该是安全的。

chy5wohz

chy5wohz2#

在C99中,你可以使用复合文字来使它内联:

unsigned long outVal = *((unsigned long *)&((float){ inVal }));

文字(float){ inVal }将创建一个具有自动存储持续时间(即堆栈分配)的变量,该变量具有定义良好的地址。
类型双关也可以使用联合而不是指针转换来完成。使用复合文字和非标准的__typeof__运算符,你甚至可以做一些宏魔术:

#define wicked_cast(TYPE, VALUE) \
    (((union { __typeof__(VALUE) src; TYPE dest; }){ .src = VALUE }).dest)

unsigned long outVal = wicked_cast(unsigned long, (float)inVal);

在优化方面,GCC更喜欢联合而不是指针转换。这可能根本不适用于MS编译器,因为有传言说它的C99支持是不存在的。

kgsdhlau

kgsdhlau3#

假设:inVal和outVal是参数。

void func(int inVal,unsigned long* outVal)
{
    float flt = (float) inVal;

    *outVal = (unsigned long)flt; // convert flot to unsigned long.
                                  // Then assign to the variable by de-ref
                                  // the pointer.
}

相关问题