2010-02-14 207 views
2

我读的是GNU PDF库的源码,尤其是它们的64位整数实现。他们将64位整数定义为两个32位整数的结构 - 高位int是有符号的,低位int是无符号的。以下是头文件中的相关代码:64位二进制补码形式的负整数

/*Definition of internal structure of the pdf_i64_t type*/ 
struct pdf_i64_s 
{ 
    pdf_i32_t high; 
    pdf_u32_t low; 
}; 

typedef struct pdf_i64_s pdf_i64_t; 

根据体系结构手册,负数用二进制补码形式表示。我有一个关于这个功能的一个疑问,但:

[从pdf-types.c代码]

void pdf_i64_assign_quick (pdf_i64_t *bignum, 
         const pdf_i32_t value, 
        pdf_status_t *p_status) 
{ 
    ASSIGN_SAFE(p_status, PDF_OK); 

    if (bignum != NULL) 
    { 
     if (value < 0) 
     { 
      bignum->high = 0xFFFFFFFF; 
     } 
     else 
     { 
      bignum->high = 0; 
     } 
     bignum->low = value; 
    } 
    else 
    { 
     ASSIGN_SAFE(p_status, PDF_ERROR); 
    } 
} 

从我读,得到一个数字的二进制补码,您需要反转所有位并添加1〜结果。在上述函数中,对于值< 0,它们只将高位设置为0xFFFFFFFF,但根本不改变低位。 “价值”的位不应该反过来,然后再加上1?有人可以解释这个吗?

谢谢。

+0

应该指出,这段代码有未定义的行为,将有符号整数类型范围以外的值赋给该类型的变量。相反,它应该分配'-1'。 – 2010-09-21 02:52:03

回答

5

你会注意到,value已经一个有符号的32位整数 - 如果它是负数,它已被适当倒置。所有需要做的是符号扩展。

0

它说该值是一个32位的int ...值应该已经在二进制补码形式,从而无需改变

3

我想你混淆了一些东西 - 否定了一些在二进制补码表示法中,您翻转所有位并添加一个。

虽然这里没有否定。这是存储一个值,并做符号扩展 - 最高位必须扩展到高32位。这是发生了什么,因为输入已经被签名,是二进制补码输入。

1

Anon已经回答了这个问题,我只是想发布一个轻微的优化,完成同样的事情没有分支。

void pdf_i64_assign_quick (pdf_i64_t *bignum, 
         const pdf_i32_t value, 
        pdf_status_t *p_status) 
{ 
    ASSIGN_SAFE(p_status, PDF_OK); 

    if (bignum != NULL) 
    { 
     bignum->high = (value >= 0) - 1; 
     bignum->low = value; 
    } 
    else 
    { 
     ASSIGN_SAFE(p_status, PDF_ERROR); 
    } 
} 

0xffffffff的是32位的十六进制为-1和(值> = 0)的计算结果为1或0,所以它也设置高到0xFFFFFFFF为value负值和为0的正值。