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 :

-2147483648, long ou pas?


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 217
    Par défaut -2147483648, long ou pas?
    Bonjour à tous.
    J'ai un petit problème dans la compilation de mon code : le compilateur m'envoie le message suivant:
    projectpath\file.c(71) : warning C4146: unary minus operator applied to unsigned type, result still unsigned

    Voilà la ligne de code sur lequel le warning porte :
    *num = -2147483648;

    Pourtant si je ne me trompe pas les "signed long int" (sur lequel num pointe) vont de -2^31 à 1^31-1, or -2147483648 = -2^31 .

    Le compilateur ne devrai donc pas considerer comme un nombre non signé.
    Je peut toujours feinter le compilateur en mettant "*num = -2147483647 - 1", mais je crois que feinter un compilateur n'est pas toujours la bonne solution pour pas truffer le code de bugs vicieux.

  2. #2
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    La norme assure qu'un entier de type signed long int peut prendre des valeurs entre 2**31 - 1 et -(2**31 - 1). Ton implantation, elle, assure des valeurs entre LONG_MIN et LONG_MAX (inclure limits.h).

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 814
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par _Michel Voir le message
    mais je crois que feinter un compilateur n'est pas toujours la bonne solution pour pas truffer le code de bugs vicieux.
    Excellent état d'esprit. En effet, il ne faut JAMAIS feinter un compilo mais au contraire toujours essayer de piger pourquoi il râle...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Par défaut
    Salut,

    La réponse de ton problème se trouve sur MSDN (définition du warning C4146) :

    Utilises INT_MIN (limits.h) au lieu de -2147483648

    (Rmq : 2 clicks sur google ont fait l'affaire...)
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    (et pour la petite histoire, Visual utilise la feinte dans son #define de INT_MIN)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par _Michel Voir le message
    Bonjour à tous.
    J'ai un petit problème dans la compilation de mon code : le compilateur m'envoie le message suivant:
    projectpath\file.c(71) : warning C4146: unary minus operator applied to unsigned type, result still unsigned

    Voilà la ligne de code sur lequel le warning porte :
    *num = -2147483648;

    Pourtant si je ne me trompe pas les "signed long int" (sur lequel num pointe) vont de -2^31 à 1^31-1 (sic), or -2147483648 = -2^31 .
    Et c'est bien le problème : 2147483648 > 2^31 - 1, n'est pas représentable par un int, il a donc le type unsigned int (le C est assez vicieux).

    L'opposé d'un non-signé est non-signé bien entendu.

    Ton "-2147483648" vaut exactement 2147483648U (sur ton implémentation, avec long : 32 bits).

    Converti en long, le résultat est -2147483648 sur la plupart des implémentations (y a t-il des exceptions parmi les implémentations qui peuvent représenter ce nombre?).

    Citation Envoyé par _Michel Voir le message
    Le compilateur ne devrai donc pas considerer comme un nombre non signé.
    Selon la norme C, si. (Rationnellement, non.)

    Citation Envoyé par _Michel Voir le message
    Je peut toujours feinter le compilateur en mettant "*num = -2147483647 - 1", mais je crois que feinter un compilateur n'est pas toujours la bonne solution pour pas truffer le code de bugs vicieux.
    "-2147483647 - 1" est la bonne solution en effet.

    En quoi c'est une feinte?

  7. #7
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par vicenzo Voir le message
    Utilises INT_MIN (limits.h) au lieu de -2147483648
    Si il a besoin de la valeur de INT_MIN, oui.

    Si il a besoin de la valeur -2147483648, non.

  8. #8
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    De toute manière, ce n'est pas portable d'utiliser cette valeur. En effet, selon la norme et comme dit plus haut, la norme garantit qu'un entier de type signed long int peut prendre une valeur entre -(2**31 - 1) et 2**31 - 1. Utiliser LONG_MIN a l'avantage d'être portable sur ce coup, mais la valeur -2147483648 codée en dur peut poser des problèmes, même avec -2147483647 - 1 (qui déborde si LONG_MIN vaut -2147483647, mais c'est rare, c'est vrai).

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  9. #9
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par corrector Voir le message
    Si il a besoin de la valeur de INT_MIN, oui.

    Si il a besoin de la valeur -2147483648, non.
    Alors le seul moyen de pouvoir utiliser cette valeur de manière portable est d'utiliser un compilateur C99 supportant le type long long. On utilise alors la valeur: -2147483648LL. Mais bon, la dernière fois que je m'y suis intéressé, le compilateur de Microsoft ne supportait pas C99 (je ne sais pas ce qu'il en est avec la nouvelle version VC++ 2008).

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  10. #10
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    La dernière vois que j'ai regardé, VC++2005 supportait long long, bien qu'il s'asseye sur pratiquement tous les autres aspects de C99...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par Thierry Chappuis Voir le message
    De toute manière, ce n'est pas portable d'utiliser cette valeur. En effet, selon la norme et comme dit plus haut, la norme garantit qu'un entier de type signed long int peut prendre une valeur entre -(2**31 - 1) et 2**31 - 1. Utiliser LONG_MIN a l'avantage d'être portable sur ce coup, mais la valeur -2147483648 codée en dur peut poser des problèmes, même avec -2147483647 - 1 (qui déborde si LONG_MIN vaut -2147483647, mais c'est rare, c'est vrai).
    En effet, ce n'est portable "que" sur les machines capables de représenter -2147483648, ce qui inclus notamment les machines en "complément à 2".

    Puisqu'il utilise -2147483648, j'ai supposé qu'il avait réellement besoin de pouvoir représenter -2147483648.

    Si en fait il a besoin de la valeur minimum d'un long, la solution correcte est effectivement LONG_MIN.

    D'ailleurs, en relisant le message original, ça pourrait être le cas :
    Citation Envoyé par _Michel Voir le message
    Pourtant si je ne me trompe pas les "signed long int" (sur lequel num pointe) vont de -2^31 à 1^31-1, or -2147483648 = -2^31 .
    mais ce n'est pas absolument certain.

  12. #12
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    La dernière vois que j'ai regardé, VC++2005 supportait long long, bien qu'il s'asseye sur pratiquement tous les autres aspects de C99...
    L'invention de long long est bien antérieure à C99.

  13. #13
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Pardon, le message de TC m'a induit en erreur.
    Donc, VC++2005 s'assoit sur tout C99.
    Y compris les modifs de la libc qui ne nécessitent aucun changement du compilateur.

    Et le pire, c'est qu'ils préfèrent modifier le standard C plutôt que s'y accorder.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  14. #14
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par corrector Voir le message
    L'invention de long long est bien antérieure à C99.
    Dans C standard, non! Il existait certainement avant sous forme d'extension non portable.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 217
    Par défaut
    Citation Envoyé par limite.h
    #define INT_MIN (-2147483647 - 1) /* minimum (signed) int value */
    Hahaha, décidement ils n'on pas trouvé mieux que moi!

    De toute manière, ce n'est pas portable d'utiliser cette valeur. En effet, selon la norme et comme dit plus haut, la norme garantit qu'un entier de type signed long int peut prendre une valeur entre -(2**31 - 1) et 2**31 - 1.
    Mais pourquoi la norme impose un truc qui mathématiquement n'est pas rigoureux ?

    En effet, ce n'est portable "que" sur les machines capables de représenter -2147483648, ce qui inclus notamment les machines en "complément à 2".
    Ca existe les machines qui ne sont pas en complement à 2?

  16. #16
    Membre chevronné Avatar de dapounet
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2007
    Messages
    469
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2007
    Messages : 469
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Pardon, le message de TC m'a induit en erreur.
    Donc, VC++2005 s'assoit sur tout C99.
    Y compris les modifs de la libc qui ne nécessitent aucun changement du compilateur.
    Il y a peut-être moyen de s'en tirer avec un typedef dans ce style-là :
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #ifdef _MSC_VER
      typedef _int64 LONG_LONG;
    #else
      typedef long long LONG_LONG;
    #endif

  17. #17
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par _Michel Voir le message
    Mais pourquoi la norme impose un truc qui mathématiquement n'est pas rigoureux ?
    Qu'est-ce que tu ne trouves pas rigoureux? On sait que si on utilise des valeurs comprises entre -(2**31 - 1) et 2**31 - 1, on a aucun problème.
    Citation Envoyé par _Michel Voir le message
    Ca existe les machines qui ne sont pas en complement à 2?
    Ca devient rare, mais ça existe.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  18. #18
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 217
    Par défaut
    Bon, bon, d'accord. C'est juste que si on réflechi pas trop (lol), on pourrai se dire qu'on travaille dans l'ensemble des nombres entiers modulo 2^32. A partir de ça les opérations comme l'addition et la soustraction avec dépassement de capacité sont tout à fait permises. Mais bon c'est sur que si à un moment il y avait des machines qui reflechissent différement, il faut avoir des normes qui marchent sur tout le monde.

  19. #19
    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
    _Michel :
    Voilà la ligne de code sur lequel le warning porte :
    *num = -2147483648;

    Pourtant si je ne me trompe pas les "signed long int" (sur lequel num pointe) vont de -2^31 à 1^31-1, or -2147483648 = -2^31 .

    Le compilateur ne devrai donc pas considerer comme un nombre non signé.
    Le problème vient de ce que les constantes entières littérales sont définies positives et non pas signées.
    -2147483648 est considéré comme une expression qui calcule l'opposé de la constante 2147483648. Or, cette valeur n'est pas représentable.
    D'où "l'artifice" (-2147483647 - 1)

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

Discussions similaires

  1. [Exchange 2007] Mais sous exchange trèès longs à arriver, pas de synchro du calendier
    Par Arnard dans le forum Exchange Server
    Réponses: 2
    Dernier message: 10/01/2013, 15h29
  2. [Tableaux] Délai de traitement d'une page pas assez long
    Par Alexlesilex dans le forum Langage
    Réponses: 14
    Dernier message: 15/05/2006, 17h40
  3. Réponses: 9
    Dernier message: 26/04/2006, 09h07
  4. Réponses: 1
    Dernier message: 20/12/2005, 17h51

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