2017-01-30 1 views
0

Ci-dessous j'ai construit un petit exemple d'un code sur lequel je travaille qui utilise des champs de bits. Lors de la mise en œuvre de l'opérateur de comparaison, j'ai remarqué que cela ne fonctionnait pas comme prévu. Le problème étant que -1 ne semble pas être inférieur à 1.construisant des champs de bits signés

Après avoir réfléchi un instant, il me semble que quelque chose ne va pas dans le masquage du constructeur.

J'ai ajouté le "aValue & MAX_VALUE" là parce que sinon le compilateur donne un avertissement de conversion. Mais masquer d'abord avec MAX_VALUE, puis lancer un int32_t ne me donne pas le bon résultat.

Est-ce que quelqu'un sait comment je peux résoudre ce problème? Je semble obtenir le résultat escompté lorsque j'écris minusOne.v = -1; dans la méthode main(). Mais je ne suis pas sûr comment je pourrais écrire cela dans le constructeur (sans obtenir l'avertissement de conversion).

#include <iostream> 
#include <cstdint> 

using namespace std; 

struct int27_t 
{ 
    int32_t v:27; 

    constexpr static int32_t MIN_VALUE = -(1L << 26); 
    constexpr static int32_t MAX_VALUE = (1L << 26) - 1; 
    constexpr static int32_t MASK = 0x7FFFFFF; 

    int27_t() : v(0) {} 

    explicit int27_t(int32_t aValue) : v(static_cast<int32_t>(aValue & MAX_VALUE)) {} 

    friend bool operator<(const int27_t& aLhs, const int27_t& aRhs); 
}; 

bool operator<(const int27_t& aLhs, const int27_t& aRhs) 
{ 
    return aLhs.v < aRhs.v; 
} 

int main() 
{ 
    int27_t minusOne{-1}; 
    int27_t plusOne{1}; 
    cout << "MAX_VALUE == " << int27_t::MAX_VALUE << " == 0x" << hex << int27_t::MAX_VALUE << dec << endl; 
    cout << "-1 == " << minusOne.v << " == 0x" << hex << minusOne.v << dec << endl; 
    cout << "-1 cast to int32_t: " << static_cast<int32_t>(minusOne.v) << " == 0x" << hex << static_cast<int32_t>(minusOne.v) << dec << endl; 
    cout << "-1 < 1 ? " << (minusOne < plusOne) << endl; 
    cout << endl; 
} 

sortie du programme

MAX_VALUE == 67108863 == 0x3ffffff 
-1 == 67108863 == 0x3ffffff 
-1 cast to int32_t: 67108863 == 0x3ffffff 
-1 < 1 ? 0 
+0

Il n'y a vraiment aucune raison d'utiliser un champ de bits ici. Sur les plates-formes modernes, cette structure sera arrondie à 32 bits de toute façon. De plus, le masquage et [le complément à deux] (https://en.wikipedia.org/wiki/Two's_complement) ne sont pas compatibles de cette façon, le bit de signe sera arraché. – tadman

+0

@tadman, je comprends le masquage avec des déchirures MAX_VALUE du bit de signe. Mais comment puis-je résoudre ce problème? Le masquage avec la valeur MASK entraîne un avertissement de conversion. – jeebee

+0

Je pense que @kamajii a d'excellents conseils et je vous encourage à le suivre. – tadman

Répondre

3

arithmétique booléenne ne fonctionne pas de cette façon sur les types signés. Vous êtes simplement & en supprimant le signe dans votre constructeur.

Il existe quatre problèmes avec votre code:

  1. Ne pas utiliser l'arithmétique binaire sur les types signés. Ne fais pas ça. Si vraiment nécessaire, arithmétiquement convertir en unsigned (multiplier par -1 et être conscient de débordement), faire quelque chose et revenir à signé arithmétiquement.
  2. Vous comptez sur une certaine représentation des nombres signés. Pour autant que je sache (qui est C99 en ce qui concerne les types signés), le langage offre trois distinctes: signe et la magnitude, son complément et complément à deux, cf. ISO/CEI 9899: TC2 §6.2.6.2-2.
  3. En supposant deux complément, qui devrait contenir pour presque toutes les plates-formes récentes, votre MIN_VALUE est éteint par un.
  4. N'utilisez pas de champs binaires, s'il vous plaît. Presque toute architecture récente l'étendra à un type de taille de mot. Vous ne gagnez probablement rien d'autre que des problèmes car le débordement signé est un comportement indéfini. Il n'y a donc aucun intérêt à restreindre la portée d'un type signé de cette façon.
+0

En lisant ceci, ça a l'air vraiment mauvais, je vais réfléchir à une approche différente sans bit-fields. Mon objectif n'était pas d'obtenir de bonnes performances, mais de simuler un autre appareil qui calcule avec certaines restrictions sur le nombre de bits (donc simulation, pas de performance). Mais cela n'a pas vraiment d'importance pour votre argument. Je vais réfléchir à comment je peux le changer. – jeebee

+0

Etes-vous sûr que mon 'MIN_VALUE' était désactivé?Cela me semble correct, il devrait y avoir une valeur négative de plus. – jeebee