2010-02-14 9 views
2

Je lisais la source de la bibliothèque PDF GNU, en particulier leur implémentation d'entiers 64 bits. Ils ont défini des entiers de 64 bits comme des structures de deux entiers de 32 bits - l'entier supérieur est signé et l'ordre inférieur int est non signé. Voici le code correspondant du fichier d'en-tête:Les nombres entiers négatifs de 64 bits sous forme de complément à deux

/*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; 

Selon les chiffres négatifs manuel d'architecture sont représentés dans deux la forme de complément. J'ai un doute au sujet de cette fonction si:

[code de 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); 
    } 
} 

D'après ce que je lis, pour obtenir le complément à deux d'un certain nombre, vous devez inverser tous les bits et ajouter 1 à le résultat. Dans la fonction ci-dessus, pour la valeur < 0, ils ne font que mettre les bits de poids fort à 0xFFFFFFFF mais ne modifient pas du tout les bits de poids faible. Les bits de 'value' ne devraient-ils pas être inversés, suivi de l'addition de 1? Quelqu'un peut-il expliquer cela?

Merci.

+0

Il convient de noter que ce code a un comportement indéfini, en affectant des valeurs hors de la plage d'un type entier signé à une variable de ce type. Au lieu de cela, il devrait attribuer '-1'. –

Répondre

5

Vous remarquerez que value est déjà un entier signé de 32 bits - s'il est négatif, il a déjà été inversé de manière appropriée. Tout ce qui doit être fait est l'extension de signe.

0

Il dit là que la valeur est une valeur ... int 32 bits serait déjà sous forme de complément à 2 donc pas besoin de changer

3

Je pense que vous mélangez quelques choses - pour nier un certain nombre en notation de complément à deux, vous retournez tous les bits et en ajoutez un.

Il n'y a pas de négation ici cependant. C'est stocker une valeur, et faire l'extension de signe - les bits supérieurs doivent être étendus à travers les 32 bits supérieurs. C'est ce qui se passe, puisque l'entrée est déjà signée, l'entrée du complément à deux.

1

Anon a déjà répondu à cette question, je voulais juste poster une légère optimisation qui fait exactement la même chose sans branchement.

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 est à -1 et (valeur> = 0) hex 32 bits est évaluée à 1 ou 0, de sorte qu'il définit aussi élevé à 0xffffffff pour les valeurs négatives de value et à 0 pour les valeurs positives.

Questions connexes