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 :

probleme déclaration constante #define


Sujet :

C

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut probleme déclaration constante #define
    Bonjour

    J'ai déclaré une constante comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define MA_CONSTANTE 0xFF
    Le problème est que j'ai le message d'alerte suivant :
    comparison is always false due to limited range of data type
    Pour le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    signed char maVariable; // variable 8 bits
     
    // ...
    // ...
     
    if(maVariable == MA_CONSTANTE){
     
    } else {
     
    }
    Comment faire pour ne pas avoir ce message (j'aimerais pour utiliser MA_CONSTANTE aussi avec des variables de type unsigned char) ?

    Merci d'avance,



    -------------------

    j'ai le même problème si je fais ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #define MA_CONSTANTE '\xff'
    // ou 
    #define MA_CONSTANTE 0b11111111

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    un char est codé sur 1 octet, soit 8 bits.
    Le tien est en plus signé, donc 1 bit est celui de signe
    Le range de valeurs d'un signed char est donc -128:127
    0xFF vaut lui 255

    donc
    comparison is always false due to limited range of data type
    qu'il suffit de traduire mot-à-mot pour comprendre.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    J'avais bien compris le problème, mais il n'y a pas moyen de définir la constante en 'binaire' et que ça fonctionne avec un signed char et un unsigned char ?

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    type           | valeur min   | valeur max
    signed char    | -128         | 127
    unsigned char  | 0            | 255
    Ton test représente
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    si (un nombre dont la valeur est toujours comprise entre -128 et 127 inclus est égal à 255)
    ... donc tu as un warning.

    Quelle constante veux-tu définir ? quel test veux-tu réaliser ?
    En tous cas celui-ci est totalement inutile et illogique, puisque toujours faux.

    Tu peux représenter ce que tu souhaites et réaliser les opérations de ton choix, tant qu'elles sont logiques et réfléchies.
    D'ailleurs pourquoi parler d'unsigned char alors que tu as un signed char. Soit tu énonces mal ton problèmes, soit tu oublies la moitié de celui-ci.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Tu cherches une constante que tu pourras comparer à une variable de n'importe quel type ou tu souhaites savoir si une variable a atteint la valeur maximale qu'elle peut contenir ?

    Si c'est le cas 1, je pense que c'est mort (en tout cas avec quelque chose d'aussi simple) ; si c'est le cas 2, tourne toi vers les constantes définissant les limites de chaque type.

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Ben en fait c'est pour traiter des chaines de caractères

    Dans un projet j'avais l'habitude de toujours utiliser des "unsigned char" pour traiter mes chaines (peut être à tord ?) et donc mes #define fonctionnaient bien.

    Or depuis que j'ai mis à jours mon compilo, il me met des warning comme quoi les chaine de caractères doivent être des nombre signés (pourquoi ? ... ça je sais pas ... je ne vois pas pourquoi un caractère devrait avoir une notion de signé)

    Ce que je voulais faire, c'est changer tous les unsigned char de chaine en signed char en modifiant au minimum le programme pour limiter le risque de bug.

    Pour le moment, la seule solution que j'ai trouvé, c'est de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #define MA_CARACTERE ((signed char)0xFF) // valeur d'un caractère spécial
    // => ecrire -1 est tout sauf intuitif pour savoir à quel caractère ça correspond
    // Est-ce que c'est valide au moins ?

  7. #7
    Membre éclairé
    Avatar de Kirilenko
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    234
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 234
    Points : 807
    Points
    807
    Par défaut
    Attention, signed char, unsigned char et char sont trois types différents.

    Pour représenter une chaîne de caractère, il faut utiliser uniquement le type char (à la rigueur, TCHAR ou wchar_t).

    Les char signés et non signés indiqués explicitement ne sont censés servir qu'à représenter des nombres qui peuvent appartenir à une plage de valeur (souvent peu importante).
    Récursivité en C : épidémie ou hérésie ?

    "Pour être un saint dans l'Église de l'Emacs, il faut vivre une vie pure. Il faut se passer de tout logiciel propriétaire. Heureusement, être célibataire n'est pas obligé. C'est donc bien mieux que les autres églises" - Richard Stallman

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    j'ai défini mes chaines de caratère avec des char mais j'ai toujours une erreur sur le #define car ça sous entend que c'est une variable de type signée

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define MON_CARACTERE ((char)0xFF) // valeur d'un caractère spécial
    => c'est correcte (selon le compilateur utilisé, char peut être signé ou non) ?

  9. #9
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    J'allais dire "pour moi, char = signed char et sont donc du même type ; unsigned char est un autre type". Puis, je me suis dit qu'il faut toujours tourné sa langue 7 fois dans sa bouche avant de parler.

    Je suis donc aller voir la FAQ de Developpez (et oui...) et j'ai trouvé cette entrée : Quelle est la différence entre char, signed char et unsigned char ?. En utilisant Eclipse sous Windows (et donc gcc visiblement), l'instruction suivante m'affiche -1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("maVariable3 = %d\n",(char)255);
    Pas bête le compilateur

    Je pense que Kirilenko a raison quand il dit
    [1]Pour représenter une chaîne de caractère, il faut utiliser uniquement le type char

    [2]Les char signés et non signés indiqués explicitement ne sont censés servir qu'à représenter des nombres
    [1] surtout quand on voit par exemple le prototype de strcpy où ce sont bien des char* qui sont utilisés.

    [2] est-ce que ça un intérêt sur un PC avec une RAM importante ? Ca doit surtout servir quand la RAM est très faible (un µC par exemple ? ^^)

  10. #10
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Bktero Voir le message
    [2] est-ce que ça un intérêt sur un PC avec une RAM importante ? Ca doit surtout servir quand la RAM est très faible (un µC par exemple ? ^^)
    pas du tout. Comme on l'a dit, pour représenter des nombres.. en binaire..

    Par exemple, pour inclure une image (gif ou jpeg par exemple) à l'intérieur d'un message et l'envoyer sur un pipe ou un socket, il est bon d'avoir un buffer de unsigned char...

    En utilisant les bons casts, puisqque la plupart des fonctions de type "send" prennent soit un void* soit un char *

    Admettons que tu veuilles fabriquer un message du stype "DATA IMAGE = .<image>...", un peu comme une balise html sauf que tu mettrais l'image dedans..

    Quand tu voudras écrire "DATA IMAGE = ", tu utiliseras des fonctions prenant des char* en entrée et/ou sortie (sprintf, etc). Par contre, lorsque tu voudras y inclure l'image, tu auras besoin des unsigned char.

    Tu déclareras donc ton buffer en unsigned char Tu feras des print de texte en castant en char*, puis des memcpy sur les unsigned char..(en particulier parce que tu peux avoir des zéros (0), et que tu ne veux pas qu'ils soient pris pour des NULL, qui termineraient la chaîne)

    Et tu l'enverras soit tel quel si la routine d'envoi prend des void* ou des unsigned char*, soit en castant si la routine d'envoi prend des char*.

    A retenir donc : si je dois formatter un message texte contenant du binaire, je dois utilser des unsigned char pour ne pas interpréter un zéro comme une fin de chaîne (bien entendu il faut avoir un caractère de fin de la partie binaire, ou inclure dedans une longueur)
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    J'ai un doute, si j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    unsigned char uval = 255;
    signed char val;
     
    val = (signed char)uval;
    => val vaudra 0xFF quelque soit le compilateur utilisé ?


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    unsigned char uval;
    signed char val = -1;
     
    uval = (unsigned char)val;
    => uval vaudra 0xFF quelque soit le compilateur utilisé ?

  12. #12
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Le signed ou le unsigned t'indiquent comme lire / interpréter les 8 bits. Y a t-il ou non un bit de signe ? Je pense que ce n'est pas dépendant du compilateur mais du mode de codage des nombres sur ta machine.
    • 0xFF = 0b11111111 = 255 si on est en non signé avec représentation binaire simple.
    • 0xFF = 0b11111111 = -1 si on est en signé avec une représentation en complément à 2.
    • 0xFF = 0b11111111 = -127 si on est en signé avec une représentation en "signe+amplitude".

    Si ta machine utilise du complément à 2 (ce qui doit être le cas de tous les ordinateurs non ?), la réponse me semble clairement être "oui".


    @souviron34 : il est vrai que je réfléchissais dans le cas de la déclaration du variable simple (genre int a=1 contre char a=1) et je ne pensais pas à des cas tordus de mixage de données ou lors d'envoi réseau pour limiter la quantité de données ! Merci pour les remarques !

  13. #13
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Citation Envoyé par boboss123 Voir le message
    J'ai un doute, si j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    unsigned char uval = 255;
    signed char val;
     
    val = (signed char)uval;
    => val vaudra 0xFF quelque soit le compilateur utilisé ?


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    unsigned char uval;
    signed char val = -1;
     
    uval = (unsigned char)val;
    => uval vaudra 0xFF quelque soit le compilateur utilisé ?
    Que dit la norme (n1256) :
    6.3.1.3 Signed and unsigned integers
    1 When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
    ce n'est pas le cas dans les deux exemples
    2 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.49)
    C'est l'exemple 2 : uval vaut 256-1 = 255 = 0xFF (avec des char de 8 bits de données)
    3 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.
    C'est le cas 1
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    ok, merci pour l'info

    donc pour la section 3, tu fais comment pour être sur d'avoir la bonne valeur quelque soit le compilo ?

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    rebonjour,

    J'ai une autre question :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    unsigned char uVal = 252;
    signed char sVal = -4;
    // les deux variables ont la même valeur binaire
     
    // ne fonctionne pas
    if(uVal  == sVal ){
    // ..
    }
     
    // fonctionne
    if(uVal  == (unsigned char)sVal ){
    // ..
    }
    => pourquoi la comparaison n'est vrai que pour le second cas ? ... dans le premier cas, sVal ne derait-il pas être implicitement converti en unsigned char ?

  16. #16
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Non, il y a pour les opérandes entières d'un type "plus petit" que int une promotion de type : si les valeurs de ce type sont représentables par un int, alors la valeur est promue en int sinon elle est promue en unsigned int.

    uVal == sVal
    uval est unsigned char 252. Après promotion, la valeur devient int 252
    sVal est signed char -4. Après promotion, la valeur devient int -4
    et 252 != -4

    uVal == (unsigned char)sVal
    uval est unsigned char 252. Après promotion, la valeur devient int 252
    sVal est signed char -4
    (unsigned char)sVal est unsigned char (256-4) = unsigned char 252
    Après promotion, la valeur devient int 252
    et 252 == 252
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  17. #17
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2012
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 190
    Points : 380
    Points
    380
    Par défaut
    salut !

    j'en ai bavé aussi. mais finalement le draft C99 :
    ...
    les cas non entiers ...
    the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands:
    If both operands have the same type, then
    no further conversion is needed.
    Otherwise, if both operands have signed integer types or both have unsigned integer types,
    the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
    Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then
    the operand with signed integer type is converted to the type of the operand with unsigned integer type.
    Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then
    the operand with unsigned integer type is converted to the type of the operand with signed integer type.
    Otherwise,
    both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.
    c'est un peu lourd, mais,
    les char, signed char, unsigned char ont le même rang,
    les int, signed int, unsigned int ont même rang,
    les types char ont un rang inferieur à celui des types int.

    j'avais commencé ce post avant le repas, mais entre temps diogene a aussi posté. ça va dans le même sens ...

    A+
    Don't want money. Got money. Want admiration.
    (A tribute to SSG)

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Merci, je commence à mieux comprendre comment tout cela fonctionne ... c'est pas simple à interpréter la norme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    	signed char varsc = 0xFA;
     
    	switch(varsc){
    		// ce test est ignoré car vaut toujours false
    		case 0xFA: // cette valeur est typée sur un int
    			printf("test OK\r\n");
    			break;
     
    		// ce test est pris en compte
    		case '\xFA': // cette valeur est typée sur un char
    			printf("test OK2\r\n");
    			break;
     
    		// déclenche un warning comme quoi c'est identique à "case '\xFA'"
    		case ((int)0xFFFFFFFA): // le cast (int) ne sert a rien car la valeur est par défaut de type int
    			printf("test OK3\r\n");
    			break;
     
    		// déclenche un warning comme quoi c'est identique à "case '\xFA'"
    		case ((signed char)0xFA):
    			printf("test OK4\r\n");
    			break;
     
    		default :
    			printf("erreur de cast\r\n");
    	}
    => ça confirme bien tout vos dire
    La constante '\xFA' est forcement de type char ou ça dépend du compilateur utilisé (avec mon compilo c'est le cas) ? ... je n'ai pas trouvé la réponse dans la doc de mon compilateur



    par contre pour ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    	signed char varsc = 0xFA;
     
    	switch(varsc){
    		// ce test est ignoré car vaut toujours false
    		case 0xFA: // cette valeur est typée sur un int
    			printf("test OK\r\n");
    			break;
     
    		default :
    			printf("erreur de cast\r\n");
    	}
     
    	// le test renvoi toujours false mais ne génère pas d'erreur à la compilation
    	if (varsc == 0xFA){ 
    		printf("test OK\r\n");
    	} else {
    		printf("erreur de cast\r\n");
    	}
    Pourquoi pour le case, le compilateur m'affiche un warning mais pas pour le if ? ça ne serait pas un bug du compilateur (c'est super dangereux) ? Vous avez le même comportement du compilo chez vous ?


    Aussi, le code suivant ne devrait-il pas généré un warning car le changement de type dans ce cas est dépendant de l'implémentation du compilo ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    	unsigned char toto = 0xFA; 
    	signed char tutu = toto;
     
    	printf("%c%c\r\n", toto, tutu); // sur mon compilo, tutu  à la meme valeur binaire que toto

  19. #19
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    case '\xFA': // cette valeur est typée sur un char
    Non, c'est un int.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    case ((int)0xFFFFFFFA): // le cast (int) ne sert a rien car la valeur est par défaut de type int
    Non, c'est un unsigned int

    Pourquoi pour le case, le compilateur m'affiche un warning mais pas pour le if ? ça ne serait pas un bug du compilateur (c'est super dangereux) ? Vous avez le même comportement du compilo chez vous ?
    Ca dépend du compilateur et des options de warning. Pour celui que j'ai essayé, il me dit "Constante hors limite dans la comparaison"

    Quelques explications :

    0xFA est un int (la valeur est représentable sur un int. Sinon, ce serait un unsigned int) valeur : 250
    (signed char)0xFA : résultat dépendant de l'implémentation. probablement -6
    varsc est signed char : résultat dépendant de l'implémentation. probablement -6


    Les constantes entières caractères ont le type int. la valeur est celle d'un type char convertie en int
    '\xFA' : Si char correspond à un signed char, sa valeur est -6 sinon si char est un unsigned char 250

    0xFFFFFFFA est un unsigned int ayant pour valeur 2^32-6
    (int)0xFFFFFFFA : résultat dépendant de l'implémentation. probablement -6
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Merci encore pour tes réponses c'est très instructif (surtout que peu de cours de langage C approfondissent le sujet)

    Citation Envoyé par diogene Voir le message
    Non, c'est un int.
    C'est compliqué tout ça
    => pourquoi ils ont créé le suffix 'u' si les constantes sont déjà en unsigned ?

    Donc pour résumer, on a bien ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    0b101 // unisgned int (valeur binaire)
    0x12 // unsigned int (valeur hexadecimale)
    2 // unsigned int ? (valeur decimale)
    -2 // int ? (valeur decimale)
    02 // unsigned int ? (valeur octal)
    '\xFA' // int (valeur hexadecimale)
    // ... j'en ai oublié ??
    => c'est pareil un int et un signed int ?
    => c'est possible que le type char soit de signe différent que le type int ?


    Citation Envoyé par diogene Voir le message
    Ca dépend du compilateur et des options de warning. Pour celui que j'ai essayé, il me dit "Constante hors limite dans la comparaison"
    J'ai le même message d'erreur mais pour les switch/case uniquement. ça ne te semble pas aberrant qu'il n'apparaisse pas pour le if (ça m'étonnerait qu'il existe une option pour activer le warning juste sur le if ) ?




    Est-ce que c'est bien comme ça que ça se passe ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    // ****************************************
    signed char varsc = 0xFA;
    // => 0xFA est un 'unsigned int' qui vaut 0x000000FA
    // => varsc = (signed char)((unsigned int)0x000000FA) = -6 (dépend de l'implémentation => valeur binaire = 'FA'h)
     
    // le test renvoi toujours false mais ne génère pas d'erreur à la compilation
    // 1- vu que varsc est un '(signed) char', il est converti en 'int' => valTmpInt = -6 (valeur binaire = 'FFFFFFFA'h)
    // 2- vu que la valeur intermédaire valTmpInt est de type 'int' et que 0xFA est de type 'unsigned int', valTmpInt est converti en 'unsigned int'
    //   => valTmpUsignedInt = (unsigned int)valTmpInt = (unsigned int)-6 = (unsigned int)'FFFFFFFA'h = 0xFFFFFFFA = 4 294 967 290
    //   => la conversion ne dépend pas de l'implémentation, c'est défini
    // 3- la comparaison se fait entre valTmpUsignedInt et 0x000000FA
    if (varsc == 0xFA){ 
    	printf("test OK\r\n");
    } else {
    	printf("erreur de cast\r\n");
    }
     
    // ****************************************
    unsigned char varuc = 0xFA;
    // => 0xFA est un 'unsigned int' qui vaut 0x000000FA
    // => varuc = (unsigned char)((unsigned int)0x000000FA) = 250
     
    // le test fonctione =>  vaut true
    // 1- vu que varsc est un '(unsigned) char', il est converti en 'int' => valTmpInt = 250 (valeur binaire = '000000FA'h)
    // 2- la comparaison se fait entre valTmpInt et '\xFA' sans besoin de modifier le type vu qu'ils sont tous les deux de type int
    if (varuc == '\xFA'){ 
    	printf("test OK\r\n");
    } else {
    	printf("erreur de cast\r\n");
    }
     
    // Pour résumer :
    // - Le premier test ne peut fonctionner que si varsc est positif, sinon le test renvera forcement false
    // - Le second test est plus rapide à executer car il y a une conversion en moins à faire

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [VBA] Probleme déclaration de variable
    Par Léponge85 dans le forum Macros et VBA Excel
    Réponses: 13
    Dernier message: 11/06/2008, 14h57
  2. Où définir les constantes #define
    Par bubulemaster dans le forum Windows Forms
    Réponses: 2
    Dernier message: 14/03/2008, 12h13
  3. Probleme déclaration fonction...
    Par bixi dans le forum Langage
    Réponses: 5
    Dernier message: 30/01/2006, 19h52
  4. Réponses: 4
    Dernier message: 14/12/2005, 17h25
  5. [Delphi 2005 Perso] Probleme déclaration de méthode
    Par alk dans le forum Delphi .NET
    Réponses: 5
    Dernier message: 08/11/2005, 16h19

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