كيف يمكنني العمل مع الزوجي على مستوى البت في المعيار C89؟

StackOverflow https://stackoverflow.com//questions/20012843

سؤال

أنا ألعب مع التنفيذ وضع علامات NaN في القليل من تنفيذ اللغة أكتب بلغة 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.هل هناك طريقة موثوقة للقيام بذلك:

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

فيما يلي نسخة من تجميعه (باستخدام Clang على OS X) وتشغيله:

$ cc -std=c89 -pedantic blort.c
$ ./a.out
The number value is 1.000000
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top