如何在 C++ 中获取 long double 值的填充位置?

How to get the padding position of a long double value in C++?

一个long double值的尾数、指数和符号的位数可以通过以下方式检测(假设iec559):

template <typename T>
constexpr uint32_t bitsInExponent() 
{
    static_assert(std::numeric_limits<T>::is_iec559);
    return std::ceil(std::log2(std::numeric_limits<T>::max_exponent-std::numeric_limits<T>::min_exponent+1));
}
// outputs 15 for long double on my machine/compiler

template <typename T>
constexpr uint32_t bitsInMantissa() 
{
    static_assert(std::numeric_limits<T>::is_iec559);
    static_assert(std::numeric_limits<T>::radix == 2);
    return std::numeric_limits<T>::digits-1;
}
// outputs 63 for long double on my machine/compiler

template <typename T>
constexpr uint32_t bitsInSign() 
{
    return 1;
}

因此,long double 的总位数是(在我的机器和编译器上)79 (63+15+1),可能是 IEEE-754 二进制 64 扩展格式。

然而,long double (sizeof(long double)) 的内存占用是 16,因此是 128 位。

浮点值的填充(那些 128-79、49 位)似乎在我的机器上用我的编译器填充了较高的位,并且大部分充满了垃圾。

我的问题是:那些1-63位总是在128位的高位吗?

如果不能保证扩展 IEEE-754 二进制 64 格式的填充位于最高位,如何检测填充位置?

试一试: https://onlinegdb.com/doL6E7WYL

权威的答案只能来自阅读 ABI 以供您实施。

但是,如果您的 long double80-bit extended precision,那么您几乎可以肯定是在 x86 上,因为据我所知,它是唯一具有硬件支持该格式的主要架构。在那种情况下,除非你有一个非常不寻常的编译器和一个非常不寻常的 ABI,否则数据将位于低 10 字节,填充在高 6 字节。 x87 加载和存储指令不考虑填充,这是提供更好对齐的最新创新,因此它们将期望指向 10 字节数据本身的指针。通过将数据放在 16 字节的低端,long double * 是指向数据的指针,可以直接用于 x87 加载或存储。如果它在其他任何地方,每次对 long double 的内存访问都需要添加适当的偏移量,这将是低效的。

非 x86 平台通常通过以下两种方式之一实现 long double

  • 要么它只是 double 的别名(C++ 标准允许这样做),在这种情况下它通常是没有填充的 binary64 双精度,并且 sizeof(long double) == 8 . MSVC++ on x86-64 does this too,并且不允许您访问硬件的 80 位扩展精度支持。

  • 或者,它是 binary128 四倍精度,在这种情况下你有 sizeof(long double) == 16 并且再次没有填充。