可靠的 C 和 C++ 标准间类型转换

6

有没有一种方式可以在C和C++中有效地进行类型转换?最好是开销较低且避免使用琐碎的预处理器技巧。

在C89中,我知道我可以这样做:

unsigned int float_bits(float num) {
    return *(unsigned int *)#
}

然而,这违反了C99的严格别名规则。因此,像这样的代码可能在各种C标准中更具可移植性:

unsigned int float_bits(float num) {
    union { float f; unsigned int i; } u;
    u.f = num;
    return u.i;
}

但我知道这不是有效的C ++,因为联合体中只能有一个成员“活动”。对于C和C ++,通常给出的解决方案是如下所示:

unsigned int float_bits(float num) {
    unsigned int i;
    memcpy(&i, &num, sizeof(int));
    return i;
}

然而,这取决于编译器能否优化调用memcpy。memcpy是唯一跨C和C++标准可移植的方法吗?


6
这里应该使用memcpy。或者干脆不要进行类型转换,这很少有必要 :) - DeiDei
2
现在,如果您发布一个回答说 memcpy 是唯一的方法,我们可以将这个问题用作所有此类未来问题的规范重复。 - Richard Critten
@DeiDei 为什么使用 memcpy 比使用 (unsigned int *)&num 更可靠(或不可靠)?(如果 sizeof(float) != sizeof(int),两者都会失败。) - Adrian Mole
关于C ++:即使sizeof(float)== sizeof(int)*(unsigned int *&num);也是UB。在这种情况下,memcpy是有效的,可以使用static_assert来检查大小是否匹配。 - Richard Critten
1
@curiousguy,“有效类型”仅适用于未分配的malloc空间,这不是本问题的情况。声明为T的变量的有效类型始终为T,无论是否进行memcpy。 - M.M
显示剩余7条评论
1个回答

7
unsigned int float_bits(float num) {
  unsigned int i;
  memcpy(&i, &num, sizeof(int));
  return i;
}

memcpy 的调用没有任何副作用,除了改变 i 以具有与 num 相同的字节。

编译器可以在这里插入库中的 memcpy 函数。同时,它们也可以插入100万个NOOPs、一个乒乓球模拟AI训练会话,并尝试在证明空间中搜索Goldbach's猜想的证明。在某些时候,你必须假设你的编译器并不敌对。

每个好的编译器都知道 memcpy 的含义。


在C语言中:这会改变有效类型吗? - curiousguy
1
@curiousguy 不。 - Language Lawyer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接