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 :

Récupérer le signe du résultat d'une opération ou retour de memcmp ?


Sujet :

C

  1. #1
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut Récupérer le signe du résultat d'une opération ou retour de memcmp ?
    Bonjour/soir


    J'aimerais savoir comment on peut récupérer le signe d'un résultat d'une opération comme une soustraction par exemple ! Je suppose qu'il va falloir user des manipulations des bits mais n'étant pas trop fortiche là dedans, comment faire ? Je suppose que le but est de récupérer le bit de signe non ?

    Mon but est un exercice où je simule si on peut dire le comportement de memcmp et je sais que cette fonction ne renvoie pas le résultat de la soustraction des premiers octets différents mais uniquement le signe du résultat (enfin à ce que j'ai pû lire), soit mais voilà...

    Est-ce vraiment ce que fait par ailleurs la fonction memcmp ? Je lit le plus souvent, surtout dans les pages man que la fonction retourne une valeur négative, zéro ou positive mais pas forcément les valeurs -1, 0, 1 !


    Merci d'avance
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  2. #2
    Membre averti Avatar de Bob.Killer
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    336
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 336
    Points : 332
    Points
    332
    Par défaut
    yo !

    pour le bit de signe c'est celui qui est tout à gauche

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    exemple (signé)
    décimal      binnaire
    1              00000001
    -1             10000001
    donc pour le teste tu utilises & pour tester le bit que tu souhaites

    exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include<stdio.h>
    #include<stdlib.h>
     
    int main()
    {
    	char i = 1;
    	if(10000000 & i)
    		printf("negatif\n");
    	return 0;
    }
    Pensez aux tutoriels programmation : http://programmation.developpez.com/cours-tutoriels/

  3. #3
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Ce qu'il y'a c'est que je dois pouvoir afficher -1, 0 ou 1 suivant les cas bien entendus décrits pour memcmp soit:

    Citation Envoyé par La page man
    La fonction memcmp() renvoie un entier négatif, nul ou positif si les n premiers octets de s1 sont respectivement inférieurs, égaux ou supérieurs aux n premiers octets de s2.
    Donc voilà le problème, est-ce que je peut par exemple retourner une valeur négative quelconque comme -8 (si telle est la différence entre le bloc 1 et 2) ou est-ce que je dois vraiment retourner -1 et dans ce cas je ne sais pas comment faire

    Mon principal but est en réalité de faire une implémentation naïve en vue de tutoriels sur la libc et plus particulièrement sur le module string et donc ces précisions me seront plus qu'utiles

    Voici mon code de test (bien sûr non optimisé) à l'heure actuelle:
    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
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
     
     
    int main (void)
    {
       unsigned char tab1 [3] = { 0x01, 0x03, 0x03 };
       unsigned char tab2 [3] = { 0x01, 0x08, 0x03 };
       unsigned char * p_tab1 = tab1;
       unsigned char * p_tab2 = tab2;
       int result = 0;
       size_t count = 3;
     
     
       while (count--)
       {
          if ((result = *p_tab1 - *p_tab2) != 0)
          {
             break;
          }
     
          p_tab1++;
          p_tab2++;
       }
     
       printf ("result = %d\n", result);
     
     
       return EXIT_SUCCESS;
    }
    Ceci vise à simuler la fonction memcmp dont je ferais une implémentation plus tard lorsque j'aurais résolu mon problème de retour de valeur
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  4. #4
    Membre expérimenté
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Points : 1 421
    Points
    1 421
    Par défaut
    Citation Envoyé par Bob.Killer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    exemple (signé)
    décimal      binnaire
    1              00000001
    -1             10000001
    c'est codé en complement a 2 (enfin, je crois me rappeler de ça, faudrais que j'ouvre la norme).
    -1 c'est !1 + 1
    soit: (sur 4bits, parce qu'apres j'ai la flegmme)
    1: 0001
    !1: 1110
    -1 = !1+1: 1111
    click my www
    ............|___
    ...................\
    .................._|_
    ..................\ /
    ..................."

  5. #5
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Mouais, c'est bien de savoir ca, nan c'est vrai ... mais ca m'aide pas plus J'ai vu ca:
    memcmp

    int memcmp(const void *s1, const void *s2, size_t n);

    The function compares successive elements from two arrays of unsigned char, beginning at the addresses s1 and s2 (both of size n), until it finds elements that are not equal:

    * If all elements are equal, the function returns zero.
    * If the differing element from s1 is greater than the element from s2, the function returns a positive number.
    * Otherwise, the function returns a negative number.
    Là encore rien d'explicite quant aux valeurs de retour alors que dans mon livre Programmation système en C sous Linux, il est dit explicitement que ce n'est pas la valeur du résultat de la soustraction des premiers octets différents entre les deux blocs mais uniquement le signe du résultat qui est renvoyé

    En testant la fonctio memcmp j'ai donc pû m'apercevoir que c'est vrai, la fonction renvoie bien une des valeurs suivante: -1, 0, 1 du moins chez moi, sous Linux

    Je pense bien que là encore tout dépend de l'implémentation mais avoird d'avantage de précision sur cette fonction et sur comment arriver à cette fin, si besoin est me serait d'une grande aide
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  6. #6
    Membre éclairé
    Avatar de D[r]eadLock
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 504
    Points : 750
    Points
    750
    Par défaut
    Le bit de signe du résultat dépend de la taille de ta variable !
    À priori, d'après la définition du manuel, tu peux retouner -8 tout le temps, mais c'est vrai que mon memcmp (glibc) retourne -1.
    Si tu veux te borner à -1,0 et 1, le plus simple est ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (result < 0) result=-1;
    if (result>0) result=1;
    Et pas besoin, de binaire, ni même de savoir comment sont représentés les nombres dans la machine.

    Rq: si tu regarde le code de la glibc, il y a ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (x!=y)
        return CMP_LT_OR_GT (x,y);
    et 
    # define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1)
    Rq2: enfin juste pour BigEndian, en LittleEndian, c'est un peu plus compliqué mais l'idée est là.

  7. #7
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Citation Envoyé par D[r]eadLock
    Le bit de signe du résultat dépend de la taille de ta variable !
    À priori, d'après la définition du manuel, tu peux retouner -8 tout le temps, mais c'est vrai que mon memcmp (glibc) retourne -1.
    Ouais c'est pour ca que je me posais la question sinon la fonction je l'aurais déjà finie

    Citation Envoyé par D[r]eadLock
    Rq: si tu regarde le code de la glibc, il y a ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (x!=y)
        return CMP_LT_OR_GT (x,y);
    et 
    # define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1)
    Je crois effectivement que je vais faire un truc dans ce genre, merci bien (à tous )
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  8. #8
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    J'ai testé ton code en comparaison avec memcpy, il donne le même resultat.

    mais si tu veux faire retourner -1, 0, 1
    Tu peut faire une fonction dans ce style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int ta_memcmp(const unsigned char *tab1, const unsigned char *tab2, size_t count)
    {
       while (count--)
       {
          if (*tab1 > *tab2) return 1;
          if (*tab1 < *tab2) return -1;
          tab1++;
          tab2++;
       }
       return 0;
    }

  9. #9
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Citation Envoyé par Lucien63
    J'ai testé ton code en comparaison avec memcpy, il donne le même resultat.

    mais si tu veux faire retourner -1, 0, 1
    Tu peut faire une fonction dans ce style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int ta_memcmp(const unsigned char *tab1, const unsigned char *tab2, size_t count)
    {
       while (count--)
       {
          if (*tab1 > *tab2) return 1;
          if (*tab1 < *tab2) return -1;
          tab1++;
          tab2++;
       }
       return 0;
    }
    Ouais sauf que les arguments doivent obligatoirement êtres du type const void * pour respecter au maximum la norme du C... Voici mon code avec son programme de test si ca interesse quelqu'un

    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
    36
    37
    38
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
     
     
    int c_memcmp (const void * s1, const void * s2, size_t n)
    {
       const unsigned char * p_s1 = s1;
       const unsigned char * p_s2 = s2;
       int ret = 0;
     
       while (n--)
       {
          if (*p_s1 != *p_s2)
          {
             return *p_s1 < *p_s2 ? -1 : 1;
          }
     
          p_s1++;
          p_s2++;
       }
     
       return ret;
    }
     
     
    int main (void)
    {
       unsigned char tab1 [3] = { 0x01, 0x08, 0x03 };
       unsigned char tab2 [3] = { 0x01, 0x03, 0x03 };
     
     
       printf ("result = %d\n", c_memcmp (tab1, tab2, 3));
       printf ("result = %d\n", memcmp (tab1, tab2, 3));
     
     
       return EXIT_SUCCESS;
    }
    Merci
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    La spécification semble ne pas définir la valeur réelle du résultat, seul son signe compte:
    http://www.opengroup.org/onlinepubs/...ns/memcmp.html

    En clair, le choix de retourner 1/-1 ou la différence t'appartient. Il est généralement plus simple et plus rapide, niveau performance, de retourner directement la différence sans test supplémentaire.
    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
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Citation Envoyé par Médinoc
    La spécification semble ne pas définir la valeur réelle du résultat, seul son signe compte:
    http://www.opengroup.org/onlinepubs/...ns/memcmp.html

    En clair, le choix de retourner 1/-1 ou la différence t'appartient. Il est généralement plus simple et plus rapide, niveau performance, de retourner directement la différence sans test supplémentaire.
    Ouais c'est pour ca que je posais la question car même la vraie fonction memcmp (du moins sur Linux) retourne les valeurs -1, 0 et 1

    Bon pour ma fonction ca m'est égal, c'est avant tout dans un but éducatif plus qu'autre chose que je fait ca, éducatif pour moi, pour approfondir mes connaissances dans les fonctions standard et les maîtriser le mieux possible puis pour les autres sur mes petits tutoriels et mon futur gros tutoriel
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  12. #12
    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
    oui..

    d'ailleurs je pense que c'est pareil avec la fonction de tri du qsort... Bien que la norme ne définisse de retour particulier à part le signe, il me semble que pas mal d'implémentations du qsort demandent +1,0,-1 car elles appliquent directement le résultalt sur l'ordre de l'algo..

    M'enfin à priori si on suit la norme pas besoin...
    "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

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Attention, si une implémentation demande 1/0/-1, elle n'est pas conforme à la norme, puisqu'elle n'accepte pas des choses que la norme dit qu'elle doit accepter.
    Citation Envoyé par [URL=http://www.opengroup.org/onlinepubs/009695399/toc.htm]The Open Group Base[/URL]
    The contents of the array shall be sorted in ascending order according to a comparison function. The compar argument is a pointer to the comparison function, which is called with two arguments that point to the elements being compared. The application shall ensure that the function returns an integer less than, equal to, or greater than 0, if the first argument is considered respectively less than, equal to, or greater than the second. If two members compare as equal, their order in the sorted array is unspecified.
    (au passage, cet article-là ne précise pas que le tri doit forcément être un quicksort... mais que dit la norme là-dessus ?)
    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.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 17/11/2010, 19h55
  2. [AC-2007] afficher le résultat d'une opération dans un champ
    Par gentelmand dans le forum Access
    Réponses: 2
    Dernier message: 01/06/2010, 16h38
  3. [8086] Afficher le résultat d'une opération
    Par jskthebest dans le forum x86 16-bits
    Réponses: 13
    Dernier message: 10/06/2009, 18h17
  4. Récupérer et trier le résultat d'une requête SQL
    Par Bodom-Child dans le forum C++Builder
    Réponses: 8
    Dernier message: 10/10/2006, 07h38
  5. Réponses: 5
    Dernier message: 17/06/2006, 12h33

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