2009-06-11 8 views
2

En C++, il est possible d'utiliser un opérateur logique où un opérateur biwise était destiné:prévenir l'utilisation abusive de l'opérateur logique au lieu des opérateurs binaires

int unmasked = getUnmasked(); //some wide value 
int masked = unmasked & 0xFF; // izolate lowest 8 bits 

la deuxième déclaration pourrait facilement être mal orthographié:

int masked = unmasked && 0xFF; //&& used instead of & 

Cela provoquera un comportement incorrect - masked sera maintenant 0 ou 1 quand il est compris entre 0 et 255. Et C++ ne se plaindra jamais.

Est-il possible de concevoir du code de telle sorte que de telles erreurs soient détectées au niveau du compilateur?

+1

Juste pour être pédant: masqué sera maintenant 0 ou une valeur non nulle dépendant du compilateur. –

+1

@Martin York: Juste pour être pédant: sur une implémentation conforme masked sera maintenant 0 ou 1. Le résultat de '&&' est un 'bool' en C++, et quand il est promu en un entier, le type' false' est converti en ' 0' et 'true' se convertit en' 1'. –

+0

Doit être vieux. Étais-je en train de repenser aux jours C? –

Répondre

4

Interdire dans vos normes de codage l'utilisation directe de toutes les opérations de bits dans une partie arbitraire du code. Rendre obligatoire pour appeler une fonction à la place.

Ainsi, au lieu de:

int masked = unmasked & 0xFF; // izolate lowest 8 bits 

Vous écrivez:

int masked = GetLowestByte(unmasked); 

En bonus, vous obtiendrez une base de code qui ne dispose pas des dizaines d'erreurs sujettes à des opérations au niveau du bit réparties dans toute il.

Seulement dans un endroit (l'implémentation de GetLowestByte et ses soeurs) vous aurez les opérations au niveau du bit. Ensuite, vous pouvez lire ces lignes deux ou trois fois pour voir si vous l'avez soufflé. Encore mieux, vous pouvez tester cette partie.

+3

Je ne voudrais pas travailler dans un endroit qui ne me permet pas d'utiliser une partie légitime de la langue dans laquelle j'écris. – shoosh

+0

@shoosh: (1) Je viens de poster une stratégie possible pour résoudre le problème. (2) Je n'interdis pas, je déplace juste ces opérations à une partie spécifique (naturellement, ce serait une classe). –

+2

L'idée entière semble assez raisonnable pour le code où les opérateurs de bits sont souvent utilisés et avec des opérateurs logiques. – sharptooth

2

Les deux opérateurs représentent des opérations valides sur des entiers, donc je ne vois aucun moyen de détecter un problème. Comment le compilateur est-il supposé savoir quelle opération vous voulez vraiment?

3

Il s'agit d'un bit Captain Obvious, mais vous pouvez bien sûr appliquer encapsulation et masquer simplement le masque dans une classe. Ensuite, vous pouvez utiliser la surcharge de l'opérateur pour vous assurer que le booléen operator&&() comme bon vous semble. Je suppose qu'une implémentation décente d'un tel "masque de sécurité" ne doit pas nécessairement être trop coûteuse en termes de performances.

+0

Je mettrais de l'argent sur les compilateurs d'optimisation (de qualité) en l'insérant. –

3

Dans certains cas, vous pourriez recevoir un avertissement du compilateur (je ne m'attendrais toutefois pas à un dans votre exemple). Un outil comme la charpie pourrait être capable de détecter les erreurs possibles.

Je pense que la seule façon d'être sûr est de définir vos standards de codage pour faire la différence entre les deux opérateurs les plus évidents - quelque chose comme:

template<typename T> 
T BitwiseAnd(T value, T mask) { return value & mask; } 

et interdire les opérateurs et & au niveau du bit |