문제

구현하려고 놀고 있어요 NaN 태깅 약간의 언어 구현에서는 C로 작성하고 있습니다.이렇게 하려면 더블을 가져와서 비트를 직접 찔러야 합니다.

이제 유니온 캐스팅을 사용하여 작업하고 있습니다.

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

그러나 공용체 유형으로의 캐스팅은 표준 ANSI C89가 아닙니다.이를 수행하는 안정적인 방법이 있습니까?

  1. ~이다 -std=c89 -pedantic 깨끗한?
  2. 엄격한 앨리어싱 규칙을 위반하지 않습니까?
  3. 다음과 같은 표현식 컨텍스트에서 사용할 수 있습니다.

    Value value = ...
    printf("The number value is %f\n", AS_NUM(value));
    
도움이 되었습니까?

해결책

다음은 깔끔하게 컴파일되고 올바르게 실행되는 것으로 보이는 빠른 개념 증명입니다.나는 사용한다 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));
}

다음은 컴파일(OS X의 Clang 사용) 및 실행에 대한 기록입니다.

$ cc -std=c89 -pedantic blort.c
$ ./a.out
The number value is 1.000000
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top