2

我正在阅读 GNU PDF 库的源代码,尤其是它们对 64 位整数的实现。他们将 64 位整数定义为两个 32 位整数的结构 - 高阶 int 是有符号的,低阶 int 是无符号的。这是头文件中的相关代码:

/*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。但是,在上述函数中,对于 value<0,它们仅将高位设置为 0xFFFFFFFF,但根本不更改低位。'value'的位不应该也反转,然后加1吗?有人可以解释一下吗?

谢谢。

4

4 回答 4

5

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

于 2010-02-14T22:50:02.573 回答
3

我认为你混淆了一些东西——用二进制补码表示否定一个数字,你翻转所有位并加一个。

不过这里没有否定。这是存储一个值,并进行符号扩展——高位必须扩展到高 32 位。这就是正在发生的事情,因为输入已经有符号,二进制补码输入。

于 2010-02-14T22:55:34.353 回答
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 对于 -1 是 32 位十六进制,并且 (value >= 0) 计算结果为 1 或 0,因此对于负值它也将高设置为 0xffffffff,对于value正值设置为 0。

于 2010-02-14T22:56:36.910 回答
0

它说该值是一个 32 位 int ...值已经是 2s 补码形式,因此无需更改

于 2010-02-14T22:52:45.557 回答