Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

boutisme et opérations sur les entiers

21 réponses
Avatar
Manuel Pégourié-Gonnard
Bonjour,

Bon, c'est un point que je crois avoir compris, mais j'aimerais juste
une confirmation (ou infirmation... et/ou précision) de votre part.

Considérons le programme suivant. Ai-je raison de croire que les
trois premiers paragraphes (jusqu'au commentaire « maintenant on dépend
du boutisme ») donnent un résultat indépendant du boutisme de la
plateforme ? Entre le deuxième et le troisième paragraphe, l'un vous
paraît-il plus lisible que l'autre ?

Merci,
Manuel.


#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main(void)
{
const uint32_t a = 0xA4A3A2A1;
uint16_t b;

/* 1. On veut récupérer les 2 octets de poids fort de a dans b */
b = a >> 16;
printf("Poids fort\nb = 0x%X\n", b);

/* 2. Maintenant les deux octets de poids faible */
b = a & 0xFFFF;
printf("Poids faible\nb = 0x%X\n", b);

/* 3. Pareil, écrit autrement */
b = a;
printf("Poids faible 2\nb = 0x%X\n", b);

/*
* À partir de maintenant les résultats dépendent du boutisme
*/
memcpy(&b, &a, 2);
printf("Premiers octets\nb = 0x%X\n", b);

memcpy(&b, ((char *) &a) + 2, 2);
printf("Derniers octets\nb = 0x%X\n", b);

return 0;
}

--
Manuel Pégourié-Gonnard - http://people.math.jussieu.fr/~mpg/

10 réponses

1 2 3
Avatar
Lucas Levrel
Le 3 décembre 2012, Manuel Pégourié-Gonnard a écrit :

Considérons le programme suivant. Ai-je raison de croire que les
trois premiers paragraphes (jusqu'au commentaire « maintenant on dépend
du boutisme ») donnent un résultat indépendant du boutisme de la
plateforme ?



Je suis de ton avis, mais je laisse aux experts la confirmation.

Entre le deuxième et le troisième paragraphe, l'un vous
paraît-il plus lisible que l'autre ?
/* 2. Maintenant les deux octets de poids faible */
b = a & 0xFFFF;
printf("Poids faiblenb = 0x%Xn", b);

/* 3. Pareil, écrit autrement */
b = a;
printf("Poids faible 2nb = 0x%Xn", b);



Dans tout bon programme, c'est équivalent puisque c'est le commentaire qui
sera lu avant l'instruction. Sinon, le nº 2 me semble mieux (on n'a pas
besoin de se référer au type des variables pour comprendre).


--
LL
Avatar
Jean-Marc Bourguet
Manuel Pégourié-Gonnard writes:

Considérons le programme suivant. Ai-je raison de croire que les
trois premiers paragraphes (jusqu'au commentaire « maintenant on d épend
du boutisme ») donnent un résultat indépendant du bou tisme de la
plateforme ?



Oui.

Entre le deuxième et le troisième paragraphe, l'un vous paraà ®t-il plus
lisible que l'autre ?



Le deuxieme montre que c'est volontaire.

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Olivier Miakinen
Bonjour,

Le 03/12/2012 09:28, Manuel Pégourié-Gonnard a écrit :

Bon, c'est un point que je crois avoir compris, mais j'aimerais juste
une confirmation (ou infirmation... et/ou précision) de votre part.

Considérons le programme suivant. Ai-je raison de croire que les
trois premiers paragraphes (jusqu'au commentaire « maintenant on dépend
du boutisme ») donnent un résultat indépendant du boutisme de la
plateforme ? Entre le deuxième et le troisième paragraphe, l'un vous
paraît-il plus lisible que l'autre ?



Je suis d'accord avec tout (même s'il m'a fallu un peu de temps pour
comprendre le troisième exemple car je n'avais pas regardé le type des
valeurs), et je suis aussi d'accord avec les réponses de Lucas et de
Jean-Marc.

Dans un vrai programme, je n'utiliserais que 1 et 2, et surtout pas
les deux derniers exemples.

--
Olivier Miakinen
Avatar
Dominique MICOLLET
Bonjour,

Manuel Pégourié-Gonnard a écrit :
Ai-je raison de croire que les
trois premiers paragraphes (jusqu'au commentaire « maintenant on dé pend
du boutisme »)
donnent un résultat indépendant du boutisme de la
plateforme ?



Oui, parce que les opérations de decalage ou de masquage ont lieu dan s les
registres du processeur, pour qui la notion de "boutisme" n'existe pas.


Entre le deuxième et le troisième paragraphe, l'un vous
paraît-il plus lisible que l'autre ?



Le deuxième est plus clair.
Il devrait d'ailleurs être écrit :
b=(uint16t)(a & 0xFFFF).

Puis je me permettre un conseil : si gcc est votre compilateur, usez de
l'option -Wall et faites la chasse aux avertissements.

memcpy(&b, &a, 2);
printf("Premiers octetsnb = 0x%Xn", b);

memcpy(&b, ((char *) &a) + 2, 2);
printf("Derniers octetsnb = 0x%Xn", b);




Je suis curieux de savoir pourquoi vous cherchez à faire ces opérat ions :
elles sont très inefficaces en terme de temps d'éxécution (accé der à une
memoire est généralement plus long que manipuler des registres).

Cordialement

Dominique.
Avatar
espie
In article <k9hnr8$jaf$,
Manuel Pégourié-Gonnard wrote:
Bonjour,

Bon, c'est un point que je crois avoir compris, mais j'aimerais juste
une confirmation (ou infirmation... et/ou précision) de votre part.

Considérons le programme suivant. Ai-je raison de croire que les
trois premiers paragraphes (jusqu'au commentaire « maintenant on dépend
du boutisme ») donnent un résultat indépendant du boutisme de la
plateforme ? Entre le deuxième et le troisième paragraphe, l'un vous
paraît-il plus lisible que l'autre ?

Merci,
Manuel.


#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main(void)
{
const uint32_t a = 0xA4A3A2A1;
uint16_t b;



Puisqu'on est en mode pinaillage, tu es au courant que ce code n'est
pas portable ? 7.18.1.1: les types uintN_t sont optionels, et ne sont
fournis par l'implementation que si celle-ci supporte des entiers de
taille adequate. Les types GARANTIS sont les uint_leastN_t et uint_fastN_t
(pour n = 8, 16, 32, 64).

Mais bon, tu peux regarder si UINT16_MAX existe, par exemple.

/* 1. On veut récupérer les 2 octets de poids fort de a dans b */
b = a >> 16;
printf("Poids fortnb = 0x%Xn", b);

/* 2. Maintenant les deux octets de poids faible */
b = a & 0xFFFF;
printf("Poids faiblenb = 0x%Xn", b);

/* 3. Pareil, écrit autrement */
b = a;
printf("Poids faible 2nb = 0x%Xn", b);
/*



Avec la reserve ci-dessus, ca marchera.

* À partir de maintenant les résultats dépendent du boutisme
*/
memcpy(&b, &a, 2);
printf("Premiers octetsnb = 0x%Xn", b);

memcpy(&b, ((char *) &a) + 2, 2);
printf("Derniers octetsnb = 0x%Xn", b);




La-encore, les deux memcpy sont stricto-sensu non portables, independamment
de l'endianess de ta plateforme: tu supposes que tes char font exactement
8 bits, ce qui se verifie avec CHAR_BIT == 8.


return 0;
}




Enfin, quand je dis, ca marchera...

tes printf sont buggues. Ils masquent une promotion, et c'est pas totalement
sur que 0x%X va t'afficher exactement ce que tu voudras (typiquement, ca
va foirer sur une plateforme 16 bits).

La bonne facon sera:

#include <inttypes.h>

printf("whatevernb = %" PRIX16 "n", b);
Avatar
Manuel Pégourié-Gonnard
Bonsoir,

et merci à tous pour vos réponses.

Dominique MICOLLET scripsit :

Entre le deuxième et le troisième paragraphe, l'un vous
paraît-il plus lisible que l'autre ?



Le deuxième est plus clair.



Il me semblait aussi.

Il devrait d'ailleurs être écrit :
b=(uint16t)(a & 0xFFFF).

Puis je me permettre un conseil : si gcc est votre compilateur, usez de
l'option -Wall et faites la chasse aux avertissements.



Hum, j'ai utilisé gcc -stdÉ9 -Wall -pedantic et il n'a rien trouvé à
redire. (J'utilise systématiquement -Wall et je ne laisse jamais traîner
un avertissement.)

memcpy(&b, &a, 2);
printf("Premiers octetsnb = 0x%Xn", b);

memcpy(&b, ((char *) &a) + 2, 2);
printf("Derniers octetsnb = 0x%Xn", b);




Je suis curieux de savoir pourquoi vous cherchez à faire ces opérations :
elles sont très inefficaces en terme de temps d'éxécution (accéder à une
memoire est généralement plus long que manipuler des registres).



Il s'agit, dans des entiers multi-précision, de déplacer des blocs de 32
bits dans le but de réduire rapidement modulo un pseudo-Mersenne. Mais
je ne cherche pas particulièrement à utiliser memcpy(), là c'était
plutôt pour contraster avec les paragraphes précédents.

--
Manuel Pégourié-Gonnard - http://people.math.jussieu.fr/~mpg/
Avatar
Manuel Pégourié-Gonnard
Marc Espie scripsit :

In article <k9hnr8$jaf$,
Manuel Pégourié-Gonnard wrote:
const uint32_t a = 0xA4A3A2A1;
uint16_t b;



Puisqu'on est en mode pinaillage,



Je ne posterais pas ici si je n'aimais pas le pinaillage :)

tu es au courant que ce code n'est
pas portable ? 7.18.1.1: les types uintN_t sont optionels, et ne sont
fournis par l'implementation que si celle-ci supporte des entiers de
taille adequate. Les types GARANTIS sont les uint_leastN_t et uint_fastN_t
(pour n = 8, 16, 32, 64).



Ah non, j'avoue que ça m'avait échappé. Et je me demandais justement
comment faisaient les plate-formes qui ont CHAR_BIT > 8 pour uint8_t, je
crois que ta remarque répond à ma question.

Mais bon, tu peux regarder si UINT16_MAX existe, par exemple.



Oui, en pratique dans le projet en question il ya déjà ce genre de
tests, donc je suis tranquille.

La-encore, les deux memcpy sont stricto-sensu non portables, independamment
de l'endianess de ta plateforme: tu supposes que tes char font exactement
8 bits, ce qui se verifie avec CHAR_BIT == 8.



Oui.

tes printf sont buggues. Ils masquent une promotion,



Tu veux dire que b sera promu en unsigned int ?

et c'est pas totalement
sur que 0x%X va t'afficher exactement ce que tu voudras (typiquement, ca
va foirer sur une plateforme 16 bits).



Hum, là j'ai peur de pas comprendre pourquoi par contre.

La bonne facon sera:

#include <inttypes.h>

printf("whatevernb = %" PRIX16 "n", b);



Ok, vu.

--
Manuel Pégourié-Gonnard - http://people.math.jussieu.fr/~mpg/
Avatar
Dominique MICOLLET
Bonjour,

Manuel Pégourié-Gonnard a écrit :
Hum, j'ai utilisé gcc -stdÉ9 -Wall -pedantic et il n'a rien tro uvé à
redire. (J'utilise systématiquement -Wall et je ne laisse jamais tr aîner
un avertissement.)




Votre remarque m'a fait peur. J'ai fait quelques essais, et il semble q ue
"all" ne signifie plus "tout" en anglais. Le transtypage automatique
dangereux est signalé par l'option -Wconversion.



Il s'agit, dans des entiers multi-précision, de déplacer des bloc s de 32
bits dans le but de réduire rapidement modulo un pseudo-Mersenne. Mais
je ne cherche pas particulièrement à utiliser memcpy(), là c'é tait
plutôt pour contraster avec les paragraphes précédents.




Là, dès qu'on cause mathématiques, je suis un peu perdu :-) (et j 'ai honte).
Toutefois lorsqu'on parle d'entier multiprécision, la granularité d u codage
ne devrait-elle pas être l'octet ?
Je conçois qu'on puisse vouloir utiliser 32 bits pour se conformer à
l'architecture du processeur : mais il va y avoir des soucis avec les
processeurs 64 bits, sauf si la bibliothèque multiprécision a pré vu cette
situation.

Cordialement.

Dominique.
Avatar
Jean-Marc Bourguet
Dominique MICOLLET writes:

Bonjour,

Manuel Pégourié-Gonnard a écrit :
Hum, j'ai utilisé gcc -stdÉ9 -Wall -pedantic et il n'a rien tro uvé à
redire. (J'utilise systématiquement -Wall et je ne laisse jamais tr aîner
un avertissement.)




Votre remarque m'a fait peur. J'ai fait quelques essais, et il semble que
"all" ne signifie plus "tout" en anglais. Le transtypage automatique
dangereux est signalé par l'option -Wconversion.



Le all n'a jamais signifié tout dans -Wall, ca a toujours ete un
sous-ensemble des warnings, dans la doc de 2.95 -- la plus vieille
facilement accessible -- "This enables all the warnings about
constructions that some users consider questionable, and that are easy
to avoid (or modify to prevent the warning), even in conjunction with
macros."

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Lucas Levrel
Le 4 décembre 2012, Jean-Marc Bourguet a écrit :

Dominique MICOLLET writes:

Manuel Pégourié-Gonnard a écrit :
Hum, j'ai utilisé gcc -stdÉ9 -Wall -pedantic et il n'a rien trouvé à
redire. (J'utilise systématiquement -Wall et je ne laisse jamais traîner
un avertissement.)



Votre remarque m'a fait peur. J'ai fait quelques essais, et il semble que
"all" ne signifie plus "tout" en anglais. Le transtypage automatique
dangereux est signalé par l'option -Wconversion.



Le all n'a jamais signifié tout dans -Wall, ca a toujours ete un
sous-ensemble des warnings



Et même -Wextra ne suffit pas à tous les activer. Apparemment il n'y a pas
d'option pour dire « vraiment tout ».

--
LL
1 2 3