2017-04-18 3 views
0

Le code:Comment les résultats des étapes intermédiaires d'une expression arithmétique sont-ils stockés lorsque tous les termes de l'expression sont uint8_t?

int main(void) { 
    uint8_t x = 3; 
    uint8_t y = 4; 
    uint8_t z = 5; 

    uint8_t a = (x - y)/z; 
    uint8_t b = x - y; 
    printf("a is %d\n", a); 
    printf("b is %d\n", b); 
    return 0; 
} 

a la sortie suivante:

a is 0 
b is 255 

Je suppose que (3 - 4)/5 entraînerait un dépassement de (3 - 4) comme uint8_t est 255. Quand une étape intermédiaire comportant des nombres entiers non signés résultats dans un nombre négatif, pourquoi ne déborde-t-il pas? Dans quel format est le résultat pour (3 - 4) stocké avant l'étape suivante / 5 se produit?

+0

'% d' n'est pas un spécificateur de format correct pour' uint8_t'. Et oui, l'arithmétique est effectuée avec les opérandes promus à «int». Donc '(x-y)' sera évalué à '-1' et aura le type' int'. –

+0

Quel compilateur utilisez-vous? 'gcc -Wall' donne comme sortie' a est 0 b est 255'. Et pour ces valeurs, je pourrais peut-être concocter une explication ensemble. – Yunnosch

+1

@EugeneSh. 'uint8_t' est promu' int' quand vous l'utilisez dans un 'printf', donc' '% d '' devrait être le bon spécificateur. – mch

Répondre

1

On peut utiliser un exemple beaucoup plus simple pour voir ce qui se passe réellement:

#include <stdio.h> 
#include <stdint.h> 

int main(void) { 
    uint8_t x = 3; 
    uint8_t y = 4; 

    int a = (x - y); 
    printf("a is %d\n", a); // a is -1 
    return 0; 
} 

(exemple en direct: http://ideone.com/C3SlIn)

Qu'est-ce que vous voyez, il est le résultat de la les promotions entières qui sont effectuées sur les opérandes à - dans le cadre des conversions arithmétiques habituelles. parties pertinentes de la définition des promotions entières de la (C99) norme:

[6.3.1.1] Si un int peut représenter toutes les valeurs du type original, la valeur est convertie en un int ; sinon, il est converti en unsigned int.

Un int peut en effet représenter toutes les valeurs d'un uint8_t, de sorte que la soustraction est vraiment équivalent à:

int a = (int)x - (int)y; 

En d'autres termes, il n'y a pas de débordement.


1. Mais pour préempter une confusion commune, ce comportement est inhérent à comment - œuvres; ce n'est pas parce que nous assignons à un int ici.