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 :

Dumper l'empreinte mémoire d'un type int


Sujet :

C

  1. #1
    Membre habitué Avatar de RaphaelG
    Homme Profil pro
    Amateur
    Inscrit en
    Juin 2016
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Juin 2016
    Messages : 94
    Points : 183
    Points
    183
    Par défaut Dumper l'empreinte mémoire d'un type int
    Bonjour à tous,

    Je cherche à visualiser la manière dont sont stockés en mémoire certains types.
    En fait je m'interessais surtout aux floats mais comme je rencontrais des difficultés, je me suis rabattu sur le type int. C'est plus facile pour moi de contrôler la justesse de ce que j'observe.

    Je travaille avec une vieille machine 32-bit sous Debian stable Jessie et le compilateur GCC livré avec la Debian stable est en version 4.9.2.

    Dans un 1er temps voilà ce que j'ai fait :
    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
     
    /* dump-int1.c
     * to compile: gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wstrict-prototypes -Wuninitialized -Wunreachable-code -o dump-int1 dump-int1.c
     *
     * It works fine but I don't like the presentation.
     * The leading byte is at the left (inside the lower memory address) and
     * the trailing byte is at the right (inside the higher memory address).
     * It's the opposite the way one writes numbers on the paper.
     */
    #include <stdio.h>
    #include <limits.h>
    #include <string.h>
    #include <stdlib.h>
     
    void usage(int rc) {
        puts("dump-int version 1");
        puts("usage: dump-int1 <signed integer>");
        printf("with <signed integer> belonging to [%d , %d]\n", INT_MIN, INT_MAX);
        exit(rc);
    }
     
    int main(int argc, char *argv[]) {
        int n;
        unsigned int i;
        unsigned char *p_uc;
        if (argc != 2) usage(1);
        if (strcmp(argv[1], "-h") == 0) usage(0);
        if ( (n=atoi(argv[1])) == 0 ) usage(1);
        printf("%d\n", n); /* to check that the conversion with atoi is ok */
        p_uc = &n;
        printf("%02x", *p_uc);
        for (i=1; i < sizeof(int); i++) {
            p_uc++;
            printf(" %02x", *p_uc);
        }
        puts("");
        return 0;
    }
    Ca compile, certes avec 1 message de warning concernant la ligne "p_uc=&n" car p_uc est un pointeur vers un unsigned char et n est int.
    Mais ça marche. J'ai fait plusieurs vérification, tout est OK. Les nombres négatifs sont bien des compléments à 2 de leurs homologues positifs.
    La seul chose qui m'embête c'est que les octets de poids forts sont à gauche et ceux de poids faible à droite. C'est l'inverse de la manière naturelle pour écrire un nombre.
    Je me suis dit qu'à cela ne tienne, je vais changer l'ordre. Mais là, j'ai rencontrés plein de difficulté.
    Après moult essais, je me suis aperçu que je pouvais rajouter ou soustraire 1 à un pointeur mais pas 3.

    Mon nouveau programme :
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
    /* dump-int2.c
     * to compile: gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wstrict-prototypes -Wuninitialized -Wunreachable-code -o dump-int2 dump-int2.c
     *
     * What I do not understand: I can't add more than 1 to a pointer.
     * p_uc=&n + 3; doesn't work
     * instead, I have to do: p_uc=&n; p_uc++; p_uc++; p_uc++;
     */
    #include <stdio.h>
    #include <limits.h>
    #include <string.h>
    #include <stdlib.h>
     
    void usage(int rc) {
        puts("dump-int version 1");
        puts("usage: dump-int1 <signed integer>");
        printf("with <signed integer> belonging to [%d , %d]\n", INT_MIN, INT_MAX);
        exit(rc);
    }
     
    int main(int argc, char *argv[]) {
        int n;
        unsigned int i;
        unsigned char *p_uc;
        if (argc != 2) usage(1);
        if (strcmp(argv[1], "-h") == 0) usage(0);
        if ( (n=atoi(argv[1])) == 0 ) usage(1);
        printf("%d\n", n); /* to check that the conversion with atoi is ok */
        /*
         * memory dump view: lower memory adress and the trailing byte are at the
         * left
         * higher memory address and leading byte are at the right */
        p_uc = &n;
        printf("memory view:  %02x", *p_uc);
        for (i=1; i < sizeof(int); i++) {
            p_uc++;
            printf(" %02x", *p_uc);
        }
        puts("");
        /*
         * Natural view with the leading byte at the left and the trailing byte at
         * the right. */
        /* p_uc=&n + sizeof(int) - 1; */   //It doesn't work !!
        /* p_uc=&n + 3; */   //It doesn't work either
        p_uc=&n; p_uc++; p_uc++; p_uc++; /* This way, it works !! */
        printf("natural view: %02x", *p_uc);
        for (i=1; i < sizeof(int); i++) {
            p_uc--;
            printf(" %02x", *p_uc);
        }
        puts("");
        return 0;
    }
    Ca compile:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    brouillons$ gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wstrict-prototypes -Wuninitialized -Wunreachable-code -o dump-int2 dump-int2.c
    dump-int2.c: In function ‘main’:
    dump-int2.c:33:10: warning: assignment from incompatible pointer type
         p_uc = &n;
              ^
    dump-int2.c:45:9: warning: assignment from incompatible pointer type
         p_uc=&n; p_uc++; p_uc++; p_uc++; /* This way, it works !! */
             ^
    Et ça marche :
    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
     
    brouillons$ ./dump-int2 1
    1
    memory view:  01 00 00 00
    natural view: 00 00 00 01
    brouillons$ ./dump-int2 -1
    -1
    memory view:  ff ff ff ff
    natural view: ff ff ff ff
    brouillons$ ./dump-int2 1024
    1024
    memory view:  00 04 00 00
    natural view: 00 00 04 00
    brouillons$ brouillons$ ./dump-int2 2147483647
    2147483647
    memory view:  ff ff ff 7f
    natural view: 7f ff ff ff
    brouillons$ ./dump-int2 -2147483648
    -2147483648
    memory view:  00 00 00 80
    natural view: 80 00 00 00
    brouillons$
    Tout cela m'amène à 2 questions :

    Comment peux t'on expliquer que :
    "p_uc=&n; p_uc++; p_uc++; p_uc++;" fonctionne,
    alors que "p_uc=&n + sizeof(int) - 1;" ne fonctionne pas ?

    Plutôt que de bidouiller dans les pointeurs comme je le fais, n'existe t'il pas une méthode plus élégante ?

    Merci de votre attention et au plaisir de vous lire.
    IMHO, you should RTFM ASAP. IHTH.

  2. #2
    Membre émérite
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    Par défaut
    Bonjour,

    arithmétique des pointeurs, c'est ce que tu peux chercher sur google pour comprendre ce qui se passe …

    En fait n est un int, donc &n est une expression de type pointeur sur int. Lorsqu'on ajoute un scalaire s (un entier) à un pointeur on se déplace de s*sizeof(type pointé) «octets».
    Ton code &n+sizeof(int)-1 fait en «octets» adresse de n + sizeof(int)* (sizeof(int)-1), ce qui n'est pas ce que tu veux.
    Tu peux passer par un cast, ici ce n'est pas vraiment dangereux ni déconseillé puisque tu sais ce que tu fais :
    p_uc=( (unsigned char*)&n) + sizeof(int) - 1.

    Sinon, plus propre … disons que tu mets tes mains dans le cambouis donc forcément tu auras de la graisse sur les doigts.
    Une autre approche est de faire du type punning en utilisant une union :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    union split_int {
      int integer;
      unsigned char bytes[4];
    };

  3. #3
    Membre habitué Avatar de RaphaelG
    Homme Profil pro
    Amateur
    Inscrit en
    Juin 2016
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Juin 2016
    Messages : 94
    Points : 183
    Points
    183
    Par défaut
    Merci Picodev.
    J'ai cherché sur google "pointer arithmetic" et cela m'a fait découvrir plein de chose.

    Ca marche avec ton cast. Et en plus gcc ne m'envoie plus le warning "assignment from incompatible pointer type".
    Il faut que je creuse le cast car je ne l'employais que pour les types de même taille comme un unsigned char casté en char.
    Ou encore pour promouvoir un type comme par exemple un int en long ou un float en double.
    Il faut que je creuse ...

    Par contre l'union me semble tout à fait adapté à ce que je veux faire.
    Je vais ré-écrire mon truc avec des unions.
    IMHO, you should RTFM ASAP. IHTH.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Êtes-vous sérieux ? Parce que ce que vous voulez faire c'est

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        int value = (*p_uc);
        unsigned char c1, c2, c3, c4;
     
        c1 = (value & 0x000000FF);
        c2 =  ((value & 0X0000FF00) >>  8);
    //  c2 = (((value & 0X0000FF00) >>  8)  & 0x000000FF);
        c3 =  ((value & 0X00FF0000) >> 16);
    //  c3 = (((value & 0X00FF0000) >> 16)  & 0x000000FF);
        c4 =  ((value & 0XFF000000) >> 24);
    //  c4 = (((value & 0XFF000000) >> 24)  & 0x000000FF);
     
        printf("memory view:  %02x %02x %02x %02x\nnatural view: %02X %02X %02X %02X", c1, c2, c3, c4, c4, c3, c2, c1)
    Et %X -> majuscule, %x -> minuscule


    Extra : Le C alloue les variables par bloc. Donc, si tu mets unsigned char *p_uc; en premier et si tu continues à incrémenter ton pointeur tu peux voir la valeur des variables i et n.

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    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 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par RaphaelG Voir le message
    Ca marche avec ton cast. Et en plus gcc ne m'envoie plus le warning "assignment from incompatible pointer type".
    Bonjour

    Il ne faut jamais négliger les warnings. Parce que concrètement, c'est un message envoyé par le compilo qui signifie "je ne suis pas certain d'avoir bien compris ce que vous voulez faire alors je vais tenter un truc" donc il compile quand-même mais dans les 3/4 des cas, il se vautre.

    Citation Envoyé par RaphaelG Voir le message
    Il faut que je creuse le cast car je ne l'employais que pour les types de même taille comme un unsigned char casté en char.
    Ou encore pour promouvoir un type comme par exemple un int en long ou un float en double.
    Généralement dans ce cas, le cast est implicite.

    Le cast ne doit s'employer que si le C a perdu la nature de l'élément. Par exemple un pointeur double qui arriverait dans une fonction plus générale dans un pointeur void. Si on veut réutiliser le double, alors il faut caster le pointeur void en pointeur double. Mais ce genre de cas est assez rare. En fait, une bonne réflexion est que si on doit faire un cast, il y a alors des chances qu'on se soit planté quelque part. Mais surtout ne jamais faire un cast pour "faire taire les warnings" parce que là, c'est comme décoller en cachant le signal "réservoir vide"...
    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]

  6. #6
    Membre habitué Avatar de RaphaelG
    Homme Profil pro
    Amateur
    Inscrit en
    Juin 2016
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Juin 2016
    Messages : 94
    Points : 183
    Points
    183
    Par défaut
    Merci à tous de votre aide.

    En résumé, j'ai 3 méthodes à ma disposition.

    1) Ma 1ère solution où je fais coincider un pointer d'int avec un pointeur d'unsigned char et ensuite j'accède au byte en ajoutant + ou - 1 au pointeur d'unsigned char.
    A la compilation, GCC me renvoie "assignment from incompatible pointer type".
    Si je veux à tout prix éviter ce warning, je peux faire le cast de picodev :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int n;
    unsigned char *p_uc;
    ...
    p_uc = (unsigned char*)&n
    Avec ce cast, je trouve qu'on est vraiment sur le coté obscur du C. cast du contenu d'un pointeur ... Ca me donne mal à la tête.
    Et j'ai bien conscience qu'il n'est que cosmétique et que comme le remarque Sve@r, il est peut être plus judicieux de vivre avec les warnings.

    2) L'union d'un int et d'un tableau d'unsigned char suggérée par picodev.
    Ah ça, c'est la vraie bonne idée ! Je m'étais toujours demandé à quoi pouvais servir l'union, bin, là j'ai trouvé.
    Du coup, j'ai réécrit mon petit programme :
    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
    39
    40
    41
    42
    43
     
    /* dump-int5.c
     * to compile: gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wstrict-prototypes -Wuninitialized -Wunreachable-code -o dump-int5 dump-int5.c
     */
    #include <stdio.h>
    #include <limits.h>
    #include <string.h>
    #include <stdlib.h>
     
    union bytesInInt {
        int n;
        unsigned char byte[sizeof(int)];
    };
     
    void usage(int rc) {
        puts("dump-int version 1");
        puts("usage: dump-int1 <signed integer>");
        printf("with <signed integer> belonging to [%d , %d]\n", INT_MIN, INT_MAX);
        exit(rc);
    }
     
    int main(int argc, char *argv[]) {
        union bytesInInt iuc;
        unsigned int i;
     
        if (argc != 2) usage(1);
        if (strcmp(argv[1], "-h") == 0) usage(0);
        if ( (iuc.n=atoi(argv[1])) == 0 ) usage(1);
        /*
         * memory dump view: lower memory adress and the trailing byte are at the
         * left
         * higher memory address and leading byte are at the right */
        printf("memory view:  ");
        for (i=0; i < sizeof(int); i++) printf(" %02x", iuc.byte[i]);
        puts("");
        /*
         * Natural view with the leading byte at the left and the trailing byte at
         * the right. */
        printf("natural view: ");
        for (i=1; i <= sizeof(int); i++) printf(" %02x", iuc.byte[sizeof(int)-i]);
        puts("");
        return 0;
    }
    C'est ma solution préférée.

    3) Les opérations logiques proposées par foetus.
    Je les ai ré-écrites pour que ça puisse compiler.
    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
     
    #include <stdio.h>
    #include <stdlib.h>
     
    int main(int argc, char *argv[]) {
        int value;
        unsigned char c1, c2, c3, c4;
     
        value=atoi(argv[1]);
        c1 = (value & 0x000000FF);
        c2 =  ((value & 0X0000FF00) >>  8);
    //  c2 = (((value & 0X0000FF00) >>  8)  & 0x000000FF);
        c3 =  ((value & 0X00FF0000) >> 16);
    //  c3 = (((value & 0X00FF0000) >> 16)  & 0x000000FF);
        c4 =  ((value & 0XFF000000) >> 24);
    //  c4 = (((value & 0XFF000000) >> 24)  & 0x000000FF);
     
        printf("memory view:  %02x %02x %02x %02x\nnatural view: %02X %02X %02X %02X\n", c1, c2, c3, c4, c4, c3, c2, c1);
    }
    Ca a le mérite de compiler sans warning (si, il y a juste un warning qui me prévient que argc n'est pas utilisé) et d'être concis (mais pas plus que ce que j'ai fait avec l'union).
    Et surtout, ça marche !
    Néanmoins, il y un truc qui méchappe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int value;
    unsigned char c1;
    ...
    c1 = (value & 0x000000FF);
    Je viens de relire mon K&R qui est d'ailleurs peu prolixe sur les opérateurs logiques. Il me dit que l'opérateur ET (&) ne s'applique que sur des entiers. Ca tombe bien parce que value a été déclarée comme int et que la constante 0x000000FF peut sans doute être aussi considéré comme un int. (signé ou non, c'est pas clair dans ma tête)
    Mais comment ce ET logique sur 2 entiers peut se transformer en 1 caractère sans que GCC n'y redise quoi que se soit malgré les options -Wall et -Wextra ?
    IMHO, you should RTFM ASAP. IHTH.

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    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 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par RaphaelG Voir le message
    Si je veux à tout prix éviter ce warning, je peux faire le cast de picodev :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int n;
    unsigned char *p_uc;
    ...
    p_uc = (unsigned char*)&n
    Avec ce cast, je trouve qu'on est vraiment sur le coté obscur du C. cast du contenu d'un pointeur ... Ca me donne mal à la tête.
    Dans ce cas, le cast se justifie. Parce que tu es en train de dire au compilo "je sais que ce que je demande est inusité mais t'inquiète pas, je gère" (et bien entendu on espère que tu vas gérer)

    Citation Envoyé par RaphaelG Voir le message
    Mais comment ce ET logique sur 2 entiers peut se transformer en 1 caractère sans que GCC n'y redise quoi que se soit malgré les options -Wall et -Wextra ?
    Parce qu'en C, tout est nombre. Et qu'un caractère n'est rien de plus qu'un nombre compris entre -128 et 127 s'il est signé ou entre 0 et 255 s'il est non signé.
    Donc le int "0x00ff" correspond au caractère "0xff" (c'est compris dans les cast implicites) et inversement le caractère "0xaa" peut être récupéré par un int qui le stockera comme étant "0xffaa" si le caractère était signé (extension du bit de signe) ou "0x00aa" si le caractère n'est pas signé.
    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]

  8. #8
    Membre habitué Avatar de RaphaelG
    Homme Profil pro
    Amateur
    Inscrit en
    Juin 2016
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Juin 2016
    Messages : 94
    Points : 183
    Points
    183
    Par défaut
    Citation Envoyé par RaphaelG Voir le message
    ...
    Je viens de relire mon K&R qui est d'ailleurs peu prolixe sur les opérateurs logiques. Il me dit que l'opérateur ET (&) ne s'applique que sur des entiers. Ca tombe bien parce que value a été déclarée comme int et que la constante 0x000000FF peut sans doute être aussi considéré comme un int. (signé ou non, c'est pas clair dans ma tête)
    Mais comment ce ET logique sur 2 entiers peut se transformer en 1 caractère sans que GCC n'y redise quoi que se soit malgré les options -Wall et -Wextra ?
    Mon Kernigham & Ritchie commence à dater. C'est la 2ème édition paru en 88 aux USA et en 90 en France. A l'époque on parlait de C ANSI et c'était la grande nouveauté
    Ca a du évoluer car maintenant je peux faire des bitwise ANDs sur tout ce qui est entier. (de char jusqu'à long long) mais pas sur les flottants.

    Citation Envoyé par Sve@r Voir le message
    ...
    Parce qu'en C, tout est nombre. Et qu'un caractère n'est rien de plus qu'un nombre compris entre -128 et 127 s'il est signé ou entre 0 et 255 s'il est non signé.
    Donc le int "0x00ff" correspond au caractère "0xff" (c'est compris dans les cast implicites) et inversement le caractère "0xaa" peut être récupéré par un int qui le stockera comme étant "0xffaa" si le caractère était signé (extension du bit de signe) ou "0x00aa" si le caractère n'est pas signé.
    Ouais, en fait lorsque le résultat du bitwise AND est envoyé dans un type plus petit, il est tronqué. On commence à ranger les bits de poids faible puis quand il n'y a plus de place on poubellise.

    Je vais considérer ce fil comme résolu.
    Merci à tous pour votre assistance, vous m'avez fort bien aidé.
    IMHO, you should RTFM ASAP. IHTH.

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Parce qu'en C, tout est nombre. Et qu'un caractère n'est rien de plus qu'un nombre compris entre -128 et 127 s'il est signé ou entre 0 et 255 s'il est non signé.
    Pour chipoter un caractère ASCII a une valeur entre 0 et 127 comprise.

    Pour de l'UTF8, cela dépend du nombre d'octets pour le code (1 à 4 octets)


    Citation Envoyé par RaphaelG Voir le message
    3) Les opérations logiques proposées par foetus.
    Je les ai ré-écrites pour que ça puisse compiler.

    Ca a le mérite de compiler sans warning (si, il y a juste un warning qui me prévient que argc n'est pas utilisé) et d'être concis (mais pas plus que ce que j'ai fait avec l'union).
    Et surtout, ça marche !
    Je tiens à préciser que cela ne fonctionne que pour du 32 bits .
    Le mieux à faire c'est faire un sizeof(XXX) et de récupérer le nombre d'octets.
    Et avec ce nombre d'octets, faire une boucle avec un masque dynamique for(mask=0xFF, octet=0; octet < nb_octets; ++octet, mask<<=8) { } (<- à peu près cela)

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 12/10/2006, 13h49
  2. Procédure stockée, transact SQL et param de type INT
    Par Samish dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 20/04/2006, 10h01
  3. [Hibernate] Pb avec type int
    Par raj dans le forum Hibernate
    Réponses: 1
    Dernier message: 31/03/2006, 21h10
  4. Réponses: 3
    Dernier message: 23/02/2006, 09h37
  5. Réponses: 9
    Dernier message: 06/07/2005, 14h20

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