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 :

Conversions de Type


Sujet :

C

  1. #1
    Membre confirmé Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Par défaut Conversions de Type
    Bonjour,

    J'ai déjà posé cette question précédemment, mais les réponse que j'ai eues étaient floues.
    Je pose donc à nouveau cette question car je suis dans une situation où la comprendre me serait d'une grande utilité.

    J'ai de la difficulté à comprendre un passage du K&R, la voici:

    Conversion rules are more complicated when unsigned operands are involved. The problem
    is that comparisons between signed and unsigned values are machine-dependent, because they
    depend on the sizes of the various integer types. For example, suppose that int is 16 bits and
    long is 32 bits. Then -1L < 1U, because 1U, which is an unsigned int, is promoted to a
    signed long. But -1L > 1UL because -1L is promoted to unsigned long and thus appears
    to be a large positive number.
    Pourquoi, reprenant l'exemple de ce passage, sur une machine ayant des int codés sur 16 bits et des long sur 32, -1L < 1U, et pourquoi -1L > 1UL ?

    De plus, j'ai de la misère à comprendre pourquoi ils font ces comparaisons (-1L < 1U et -1L > 1UL)... Dans le cas de -1L < 1U, je sais bien que -1 est plus petit que 1, peu importe le type. Par contre, je ne comprends pas pourquoi -1 peut-être plus grand que 1. J'en déduis que ce doit être au niveau de la représentation binaire, avec le complément de deux et le bit de signe...

    Si vous pouviez m'expliquer cela en détails, en expliquant les étapes respectives de votre raisonnement, ce serait fort apprécié...

    Je vous remercie,

    Sincèrement,

    Array

  2. #2
    Membre émérite Avatar de orfix
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 707
    Par défaut
    Le type du résultat d'une expressions dépend de celui de ces opérandes ( garantissant le moins de perte exemple : float <-- int (op) float ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    1 - long double
    2 - double
    3 - float
    ...etc
    Dans le premier exemple -1L < 1U le 1U sera promu en L(signé) aucun soucis.
    Cependant avec le deuxième exemple les choses se corse -1L > 1UL le -1L(signé) sera promu en L(non-signé=U) sachant que sa représentation binaire ( complément à deux ) est 0xFFFFFFFF je te laisse faire le calcul c'est la plus grande valeur possible sur 32 bits

    une solution serais de faire un cast: -1L > (long)1UL

  3. #3
    Membre confirmé Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Par défaut
    Je vois...

    Donc, dans le cas de -1L > 1UL, le -1L sera converti en UL parce que c'est tjrs le plus grand type qui est promu. Cependant, on peut régler cela en convertissant la bonne opérande, le 1UL en signed long (L).

    Merci ,

    Je comprends,

    Array

  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
    Lorsqu'une expression combine deux grandeurs arithmétiques, le compilateur utilise pour son évaluation un type commun T dans lequel il convertit les opérandes puis réalise l'opération.
    Le principe est simple, sa mise en oeuvre l'est moins

    . Si les deux opérandes sont d'un type réel, le type commun sera le type réel "le plus précis"
    Exemple float et double -> double. Dans ce cas les deux valeurs sont conservées.

    . Si un opérande est d'un type réel et l'autre d'un type entier, le type commun est le type réel
    Exemple int et float -> float. Dans ce cas les deux valeurs sont (au moins approximativement pour le type entier) conservées.

    . La difficulté vient lorsque les deux opérandes sont entiers, mais on essaye également de conserver les valeurs dans la conversion.

    Les types sont classés suivant un rang avec par rang croissant :
    - char, signed char, unsigned char
    - short, unsigned short
    - int, unsigned int
    - long, unsigned long
    - long long, unsigned long long

    1- D'abord, les opérandes d'un rang inférieur à int sont convertis en int (ou en unsigned int si les valeurs de ce type ne peut être représentées sur un int, par exemple si l'opérande est de type unsigned short et que les short et les int font 16 bits). C'est la promotion des petits entiers.

    Les deux opérandes sont maintenant d'un type T1 et T2 ayant un rang supérieur ou égal à celui de int. Disons que T2 est de rang supérieur ou égal à T1


    2- Si toutes les valeurs de type T1 peuvent être représentées par le type T2, le type commun est T2. Les valeurs sont alors conservées.
    C'est le cas où T1 et T2 sont tous deux des types signés ou tous deux des types non signés et parfois le cas lorsque T1 est un type non signé de rang inférieur au type signé T2

    Sinon, le type commun est la version non signée de T2
    Le choix d'utiliser ici un type non signé comme type final se justifie parce que la transformation d'un nombre signé en un nombre non signé est bien définie par la norme alors que l'inverse ne l'est pas.


    En conséquence :

    -1L < 1U est vrai pour des machines où un int est sur 16 bits et un long sur 32 : un unsigned int peut être représenté par un long. Le type commun est long

    -1L < 1U est faux pour des machines où un int et un long sont sur 32 bits : un unsigned int ne peut être représenté par un long et le type commun sera unsigned long. Le -1L devient après la conversion 2^32 - 1

    -1L < 1UL est toujours faux, le type commun est unsigned long

    -1L < 1 est toujours vrai, le type commun est long

    -1 < 1U est toujours faux , le type commun est unsigned int

  5. #5
    Membre confirmé Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Par défaut
    C'est très bien expliqué, merci beaucoup diogene

    Prenons ce debut de code à titre d'exemple sur une machine ayant les long à 16 bits.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    #include <stdio.h>
     
    int main(void) {
            signed long i = 0xFFFF;   /* -32768 - Valeur minimale sur un signed long codé sur 16 bits */
            unsigned long j = 0xFFFF; /* 65535 - Valeur maximale sur un unsigned long codé 16 bits */
     
    [...]
    }
    Si l'on compare les variables "i" et "j", le type commun sera donc "unsigned long". Même si i est signé. C'est bien cela?

    Merci!

    Je vous remercie,

    Cordialement,

    Array

  6. #6
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    Citation Envoyé par Array Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    signed long i = 0xFFFF;   /* -32768 - Valeur minimale sur un signed long codé sur 16 bits */
    la valeur dépend du codage utilisé (sign magnitude, complément à 1, à 2 et du padding). La grande majorité des machines étant en complément à 2, ça sera plutôt -1.

  7. #7
    Membre confirmé Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Par défaut
    Euh, en effet, j'ai commi une bévue.

    Je rectifie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    #include <stdio.h>
     
    int main(void) {
            signed long i = 0x8000;   /* -32768 - Valeur minimale sur un signed long codé sur 16 bits */
            unsigned long j = 0xFFFF; /* 65535 - Valeur maximale sur un unsigned long codé 16 bits */
     
    [...]
    }
    Le type de comparaison sera unsigned long.

Discussions similaires

  1. [DATE][CONVERSION] du type numerique au type date
    Par hamed dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 06/04/2005, 16h16
  2. Conversion de type
    Par sovitec dans le forum Langage
    Réponses: 5
    Dernier message: 15/12/2004, 14h29
  3. Conversion de type
    Par poirier dans le forum ASP
    Réponses: 2
    Dernier message: 06/07/2004, 10h30
  4. [MYSQL] conversion de type sur import de script
    Par sebos63 dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 27/08/2003, 10h00
  5. Réponses: 2
    Dernier message: 05/06/2002, 12h29

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