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