標準C89のビットレベルで2倍の作業方法は?
-
21-12-2019 - |
質問
私は Nan Tagging 少し言語の実装ではC.に書いています。これを行うために、私は二重とポークをそのビットに直接服用する必要があります。
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)))
.
しかし、ユニオンタイプへのキャスティングは標準ANSI C89ではありません。これを行うための信頼できる方法は次のとおりです。
- は
-std=c89 -pedantic
クリーンですか? - 厳密なエイリアシングルールの概要を実行しませんか?
-
はこのような式の文脈で使用できます:
Value value = ... printf("The number value is %f\n", AS_NUM(value));
解決
これはきれいに編集して私のために正しく実行されているように見える迅速な概念です。Finesse Type-Punの問題に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を持つ)と実行されているITの成績証明書です:
$ cc -std=c89 -pedantic blort.c
$ ./a.out
The number value is 1.000000
. 所属していません StackOverflow