IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

soustraction de nombres non signés


Sujet :

C

  1. #1
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 854
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 854
    Par défaut soustraction de nombres non signés
    bonjour,

    j'ai une fonction getTimer() qui me renvoie la valeur d'une base de temps sur un unsigned char (en seconde).
    => je voudrais exécuter un évènement toutes les 5 secondes. Le problème est que se passe t-il lorsqu'il y a un rool over ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    unsigned char oldVal;
    oldVal = getTimer(); // recuperation de la valeur
     
    while(1){
       if (getTimer() - oldVal >= 5){
          printf("interrupt on\n");
          oldVal = getTimer();
       }
    }
    Donc si on a oldVal = 255 et getTimer() = 1 => on a 2 secondes de différence

    si je vais le calcul (1 - 255), ça donne en binaire (00000001 - 11111111)

    00000001
    - 11111111
    ------------
    00000010

    Ce qui vaut bien 2 : pouvez-vous me confirmer que j'aurais bien toujours le bon résultat ?

    y a t-i lune autre methode plus rapide pour faire cela (sans changer le type des variables car je suis un un CPU 8 bits) ?
    car le code suivant ne fonctionne pas au niveau du roll-over (suppression de la soustraction) :
    => ce qui est normal
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    unsigned char oldVal;
    timeOut = getTimer() + 5;
     
    while(1){
       if (getTimer() >= timeOut ){
          printf("interrupt on\n");
          timeOut = getTimer() + 5;
       }
    }

  2. #2
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Ce qui vaut bien 2 : pouvez-vous me confirmer que j'aurais bien toujours le bon résultat ?
    Non, ce calcul, getTimer() - oldVal, est faux en C :

    Dans cette expression, les deux termes sont des unsigned char. Avant soustraction, ils vont être automatiquement converti en int, l'opération sera faite entre int et le résultat est un int.

    Avec les valeurs oldVal = 255 et getTimer() = 5 , getTimer() - oldVal donnera 5-255 = -250 (un int) et non pas 6 :
    getTimer() - oldVal >= 5 est donc FAUX

    Par contre, (unsigned char)(getTimer() - oldVal) vaut dans ce cas 256-250 = 6 (un unsigned char). Dans l'expression suivante, l'unsigned char 6 sera converti en l'int 6 puis comparé avec l'int 5 :
    (unsigned char)(getTimer() - oldVal) >= 5 donnera VRAI

  3. #3
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 854
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 854
    Par défaut
    Citation Envoyé par diogene Voir le message
    Avant soustraction, ils vont être automatiquement converti en int, l'opération sera faite entre int et le résultat est un int.
    Est-ce vrai même sur un système 8 bits ? c'est la norme du C qui dit (que dit-elle exactement ?... que lorsque qu'il y a une soustraction il y a une conversion des variable en signés au type de taille supérieur ?) ?

    Et si getTimer() me renverrait un unsigned long, ça fonctionnerait pareil ?

  4. #4
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Pour les opérations où interviennent deux grandeurs arithmétiques, la norme précise comment déterminer un type commun aux deux opérandes pour effectuer l'opération.
    Cette détermination commence par la promotion des opérandes de type entiers : Cette promotion concerne les entiers d'un rang inférieur à int (char, short, unsigned char,...) : chaque opérande est promue en int (si toutes les valeurs possibles du type initial peuvent être conservées par cette promotion) ou en unsigned int (si ce n'est pas le cas. Par exemple, sur certaines machines un short peut être de la même taille qu'un int, alors, pour ces machines, un unsigned short sera promu en unsigned int). Ceci fait, les opérandes entières sont d'un rang supérieur à int et une deuxième étape peut commencer pour trouver un type commun pour faire l'évaluation.

    Et si getTimer() me renverrait un unsigned long, ça fonctionnerait pareil ?
    Dans ce cas, pour évaluer getTimer() - oldVal, (unsigned long)-(unsigned char), oldval serait promu en int et on évaluerait comme (unsigned long)-(int).
    Le type commun, dans ce cas, serait unsigned long et le int serait transformé en ce type. L'évaluation serait (unsigned long)-(unsigned long). Le résultat est du type unsigned long

    Dans ton cas, pour obtenir le résultat souhaité, c'est à dire forcer le "roll-over", tu peux écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ((unsigned char)(getTimer() - oldVal) >= 5){....

  5. #5
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 854
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 854
    Par défaut
    ok merci pour la reponse

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 15/07/2015, 08h48
  2. Réponses: 6
    Dernier message: 08/06/2012, 13h42
  3. Nombres non-signés en java ?
    Par cedouche dans le forum Langage
    Réponses: 6
    Dernier message: 25/06/2007, 15h07
  4. Réponses: 9
    Dernier message: 12/10/2006, 00h36
  5. Réponses: 3
    Dernier message: 05/09/2006, 00h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo