C语言 NAN盒负整数

dwbf0jvd  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(123)

我一直在关注这篇解释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


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

crcmnpdw

crcmnpdw1#

我想这里真实的问题是:
INTP不能正常工作,对于负整数返回0
由于一个bug,它不起作用。这篇文章的作者并不关心负整数,他只是验证了这个想法是可行的-也就是说,有空间容纳32位数据。负数会干扰代码,因为它们已经将一些标记位设置为1。要将标记位设置为所需的值,首先将它们清除为0,然后与值进行逐位OR。
指针也是如此--它们的最高有效位可以是二进制1111,但这样的指针通常是保留给操作系统内核的。就像整数一样--这个bug存在,但只针对较少使用的值。

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

字符串

相关问题