在标准C89中,如何在位级别使用双工?

在标准C89中,如何在位级别使用双工?,c,bit-manipulation,nan,c89,language-implementation,C,Bit Manipulation,Nan,C89,Language Implementation,我正在玩弄用C语言编写的一个小的语言实现。要做到这一点,我需要一个double并直接戳它的位 我现在使用union casting使其工作: 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

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

我现在使用union casting使其工作:

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)))

这是一个概念的快速证明,它编译干净,对我来说似乎运行正常。我使用
memcpy
来巧妙地处理类型双关语问题。这在真实的系统中当然是不可接受的,但它至少是可移植的。同样,我不知道您是否打算要求将
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));
}

很不错的。进行函数调用,然后调用memcpy并返回结果的副本,仅仅重新解释完全相同的位似乎有点无足轻重,但查看程序集输出,编译器似乎会对其进行优化。谢谢<代码>无符号长在许多系统中是32位。您可能应该从
stdint.h
使用
uint64\u t
:不幸的是,这是一个C99头。为什么要使用C?现在大多数编译器至少支持C 1999,而C 1999(tC3)支持通过联合使用别名。除非有令人信服的理由,否则新软件不应使用旧的、被替换的语言编写。
#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));
}
$ cc -std=c89 -pedantic blort.c
$ ./a.out
The number value is 1.000000