c - 我如何在标准 C89 的位级处理 double ?

标签 c bit-manipulation nan c89 language-implementation

我正在玩弄实现 NaN tagging在我用 C 编写的一个小语言实现中。要做到这一点,我需要取一个 double 并直接戳它的位。

我现在使用 union 类型转换工作:

typedef union
{
  double num;
  unsigned long bits;
} Value;

/* A mask that selects the sign bit. */
#define SIGN_BIT (1UL << 63)

/* The bits that must be set to indicate a quiet NaN. */
#define QNAN (0x7ff8000000000000L)

/* If the NaN bits are set, it's not a number. */
#define IS_NUM(value) (((value).bits & QNAN) != QNAN)

/* Convert a raw number to a Value. */
#define NUM_VAL(n) ((Value)(double)(n))

/* Convert a Value representing a number to a raw double. */
#define AS_NUM(value) (value.num)

/* Converts a pointer to an Obj to a Value. */
#define OBJ_VAL(obj) ((Value)(SIGN_BIT | QNAN | (unsigned long)(obj)))

/* Converts a Value representing an Obj pointer to a raw Obj*. */
#define AS_OBJ(value) ((Obj*)((value).bits & ~(SIGN_BIT | QNAN)))

但是转换为 union 类型不是标准的 ANSI C89。有没有可靠的方法来做到这一点:
  • -std=c89 -pedantic干净的?
  • 不会违反严格的别名规则吗?
  • 可以在这样的表达式上下文中使用:
    Value value = ...
    printf("The number value is %f\n", AS_NUM(value));
    
  • 最佳答案

    这是一个快速的概念验证,它编译干净并且对我来说似乎可以正确运行。我用 memcpy来解决打字双关问题。这在真实系统中当然是 Not Acceptable ,但它至少是可移植的。同样,我不知道您是否打算要求 AS_NUM实现为宏。

    #include <stdio.h>
    #include <string.h>
    
    typedef struct {
        char raw[sizeof(double)];
    } Value;
    
    static Value valueFromDouble(double d) {
        Value result;
        memcpy(result.raw, &d, sizeof(result));
        return result;
    }
    
    static double AS_NUM(Value value) {
        double result;
        memcpy(&result, value.raw, sizeof(result));
        return result;
    }
    
    int main(int argc, char **argv) {
        Value value = valueFromDouble(1.0);
        printf("The number value is %f\n", AS_NUM(value));
    }
    

    这是它编译(在 OS X 上使用 Clang)并运行的记录:
    $ cc -std=c89 -pedantic blort.c
    $ ./a.out
    The number value is 1.000000
    

    关于c - 我如何在标准 C89 的位级处理 double ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20012843/

    相关文章:

    c - Win32 DLL/引用存储

    c - 仅使用两个字符打印迷宫

    ios - 如何分解涉及移位运算符的表达式? swift

    Java:检查长整型中是否设置了特定位

    python - 捕获我在计算中得到 NaN 的那一刻

    fortran - 无法使用通常的自等式来识别 nvfortran 中的 nan

    c - 如何在 C 中逐行读取输入文本直到 EOF?

    c - 链表的免费功能不起作用

    java - 将字节与 0b1111_1111 按位与有何作用?

    javascript - Number.isNaN 在 IE 中不存在