2017-01-13 3 views
1

Je suis assez certain que soustraire un uint8_t d'un autre devrait aboutir à un autre nombre non signé, mais certains de mes résultats me confondent.Y at-il une différence entre unaire et n -

uint8_t a = 2; 
    uint8_t b = 1; 
    uint8_t c = -a; 
    long d = b - a; 
    long e = b + c; 

Quand j'obtenir la valeur de d il produit -1, alors que e est que je me attends 255. Ceci est un bug avec la version de gcc J'utilise ..... non?

Pour référence, j'utilise le compilateur arm-none-eabi-g++ pour mon MSP-432. Regardant this semble indiquer que gcc semble juste faire la même erreur ici.

En regardant this SO question, il semble que godbolt et le bras gcc est faux.

Que se passe-t-il ici?

+0

spécificateur de conversion utilisé, s'il vous plaît? –

+1

En C, vous ne pouvez pas utiliser des types plus petits que 'int'. Rechercher des conversions implicites – Olaf

+2

Promotions d'entier dans le cadre de conversions arithmétiques. Le résultat est que vous ne pouvez pas utiliser les alias de type taille dans le but de l'arithmétique modulaire! Les alias de type n'encodent pas le rang de conversion. –

Répondre

6

Ceci est un bug avec la version de gcc que j'utilise ..... non?

Non, ce n'est pas le cas. Quelque chose d'aussi simple que d'être bogué dans un gros compilateur comme gcc est hautement improbable.

Qu'arrive-t-est en raison des « conversions arithmétiques habituelles », en particulier « la promotion entière »:

Le - unaire favorise a à int, le (int)-2 obtient reconverti en uint8_t dans l'affectation, ce qui donne c == 254 (qui est le représentant de la classe d'équivalence de -2 dans Z mod 2^8 qui se trouve dans [0, 2^8)).

De même, le + et - binaire dans les lignes ci-dessous qui font la promotion de int, donc nous nous retrouvons avec

d == (int)b - (int)a == (int)1 - (int)2 == -1 

et

e == (int)b + (int)c == (int)1 + (int)254 == 255 

Alors tout fonctionne bien comme prescrit par la norme .

2

La raison est que les opérateurs binaires subissent promotion intégrale avant de faire le travail, et depuis int peut contenir toutes les valeurs possibles de uint8_t, ce choix est utilisé (voir http://en.cppreference.com/w/cpp/language/implicit_conversion#Integral_promotion). Ainsi, la soustraction est effectuée en tant qu'opération signée.

Lors du calcul e l'acte de stocker une valeur dans c déjà donné lieu à votre prévu modulo les mathématiques, le stockage 254 qui est ensuite ajouté à la valeur de b 1.