NAN 框负整数

问题描述 投票:0回答:1

我一直在关注这篇解释 nan boxing 的文章 https://piotrduperas.com/posts/nan-boxing 并尝试用我自己的“语言”来实现它。

typedef union {
    uint64_t as_uint;
    double as_double;
} Atom;

#define NANISH      0x7ffc000000000000 /* distinguish "our" NAN with one additional bit */
#define NANISH_MASK 0xffff000000000000 /* [SIGN/PTR_TAG] + 11*[EXP] + 2*[NANISH] + 2*[TAG] */

#define BOOL_MASK   0x7ffe000000000002  /* 2 ms + and 2 ls */
#define NULL_VALUE  0x7ffe000000000000  /* 0b*00 */
#define TRUE_VALUE  (BOOL_MASK | 3)     /* 0b*11 */
#define FALSE_VALUE (BOOL_MASK | 2)     /* 0b*10 */

#define INT_MASK 0x7ffc000000000000 /* use all of mantisa bits for integer */
#define SYM_MASK 0xfffc000000000000 /* pointers have sign bit set */
#define STR_MASK 0xfffe000000000000 /* on x86-64 ptr* is at max 48 bits long */
#define OBJ_MASK 0xfffd000000000000 /* which is small enought to put in mantysa */
#define PTR_MASK 0xf000000000000000

/* predicates */
#define DOUBLP(v) ((v.as_uint & NANISH) != NANISH)
#define NULLP(v)  ((v.as_uint == NULL_VALUE)
#define BOOLP(v)  ((v.as_uint & BOOL_MASK) == BOOL_MASK)
#define PTRP(v)   ((v.as_uint & PTR_MASK) == PTR_MASK)
#define INTP(v)   ((v.as_uint & NANISH_MASK) == INT_MASK)
#define STRP(v)   ((v.as_uint & NANISH_MASK) == STR_MASK)
#define SYMP(v)   ((v.as_uint & NANISH_MASK) == SYM_MASK)
#define OBJP(v)   ((v.as_uint & NANISH_MASK) == BOJ_MASK)

/* get value */
#define AS_DOUBL(v) (v.as_double)
#define AS_BOOL(v)  ((char)(v.as_uint & 0x1))
#define AS_INT(v)   ((int32_t)(v.as_uint))
#define AS_PTR(v)   ((char *)((v).as_uint & 0xFFFFFFFFFFFF))

/* add tag mask */
#define TO_VEC(p) ((uint64_t)(p) | VEC_MASK)
#define TO_STR(p) ((uint64_t)(p) | STR_MASK)
#define TO_SYM(p) ((uint64_t)(p) | SYM_MASK)
#define TO_MAP(p) ((uint64_t)(p) | MAP_MASK)
#define TO_SET(p) ((uint64_t)(p) | SET_MASK)
#define TO_INT(i) ((uint64_t)(i) | INT_MASK)

我添加了一些额外的对象供自己使用,但想法应该是相同的。

int main() {
    Atom atom;
    atom.as_uint = TO_INT(-3);
    printf("%d\n", AS_INT(atom));
    printf("%d\n", INTP(atom));
    printf("%x\n", AS_INT(atom));

}

输出:

-3
0
fffffffd

因此,根据我的理解,负 int 存储在 U2 系统中,这解释了为什么所有位都被反转并且这种表示与 INT_MASK 不匹配,我正在考虑将 INT_MASK 更改为 0xfffff 但它与无符号的原始表示冲突int(和其他掩码)。我是否误解了文章中的某些内容? INT_MASK 的正确值是多少?

c variables language-design data-representation
1个回答
0
投票

我想这里真正的问题是:

INTP 无法正常工作,对于负整数返回 0

由于错误,它无法工作。文章作者并不关心负整数,他只是验证了这个想法是否有效——即有空间容纳 32 位数据。负数会干扰代码,因为它们已经将一些标记位设置为 1。要将标记位设置为所需值,请首先将它们清除为 0,然后与该值进行按位或运算。

指针实际上也是如此——它们的最高有效位可以有二进制 1111,但这样的指针通常保留给操作系统内核。就像整数一样 — 该错误存在,但仅针对较少使用的值出现。

#define CLEAR_TAG_BITS(x) ((uint64_t)(p) & ~NANISH_MASK)
#define TO_STR(p) (CLEAR_TAG_BITS(p) | STR_MASK)
#define TO_INT(i) (CLEAR_TAG_BITS(i) | INT_MASK)
...
© www.soinside.com 2019 - 2024. All rights reserved.