我可以通过 IEEE double 往返对齐指针吗?

标签 c ieee-754

我可以通过 double 往返任何 4 字节对齐的指针吗?我可以通过字符串往返任何有限 double 吗?

具体来说,在任何使用符合 C11 的 IEEE float 且静态断言均未失败的平台上,是否保证以下程序中的断言通过?

#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <math.h>

int main(void) {
   struct {
      void *dummy;
   } main_struct;
   main_struct.dummy = 0;
   static_assert(_Alignof(main_struct) >= 4,
                 "Dummy struct insufficiently aligned");
   static_assert(sizeof(double) == sizeof(uint64_t) && sizeof(double) == 8,
                 "double and uint64_t must have size 8");
   double x;
   uint64_t ptr = (uint64_t)&main_struct;
   assert((ptr & 3) == 0);
   ptr >>= 2;
   memcpy(&x, &ptr, 8);
   assert(!isnan(x));
   assert(isfinite(x));
   assert(x > 0);
   char buf[1000];
   snprintf(buf, sizeof buf, "Double is %#.20g\n", x);
   double q;
   sscanf(buf, "Double is %lg\n", &q);
   assert(q == x);
   assert(memcmp(&q, &ptr, 8) == 0);
}

最佳答案

Specifically, on any platform that uses IEEE floating point, which conforms to C11, and on which neither static assertion fails, are the assertions in the following program guaranteed to pass?

只有那些要求,然后没有。排除它的原因如下:

  • 您尚未断言指针的大小为 64 位或更小。
  • 没有人说指针和 double 在内存中使用相同类型的字节顺序。如果指针是 big-endian 而 double 是 little-endian(或 middle-endian,或使用其他一些奇怪的内存格式),那么您的移位不排除负值、无限值或 NaN 值。
  • 不能保证指针简单地转换为整数值,低位位保证为零只是因为它们指向对齐的值。

这些反对意见在当前的实际平台上可能有些病态,但在理论上肯定是正确的,并且您的要求列表中没有任何内容反对他们。

例如,完全可能想象一个具有独立浮点协处理器的架构,该处理器使用与主整数 CPU 不同的内存格式。事实上,维基百科文章实际上states有真实的架构示例可以做到这一点。至于奇怪的指针格式,C FAQ 提供了一些 interesting historical examples .

关于我可以通过 IEEE double 往返对齐指针吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42229628/

相关文章:

c - 嵌入式 C 程序任务堆栈中未使用的间隙

c++ - 如何在 XWindows 中获取装饰窗口的内部尺寸?

java - 为什么将 Double.NaN 转换为 int 不会在 Java 中抛出异常?

c - C 规范中 float 的最大位数

c - linux clone() 成功,但是 child 崩溃了

c - 字符数组不打印每个值

c - 如何将文件读入结构数组?

java - 如何在 Fortran 77 和 Java 数字代码之间获得机器精度协议(protocol)?

使用 c - printf 将 ieee 754 float 转换为十六进制

javascript - 如何将按位运算应用于 JS 数字的实际 IEEE 754 表示?