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

Types entiers, questions de taille

Aucune réponse
Avatar
Manuel Pégourié-Gonnard
Bonjour,

Quelques petites questions sur les types entiers :

1. La norme C89 spécifie long int, qui doit être un type entier d'au
moins 32 bits de large. Ce type est-il vraiment implémenté par tous les
compilos, y compris quand la cible est un environnement très restreint
(genre microcontroleur 8 bits) ?

2. A-t-on des garanties sur la taille minimum de size_t ? Je n'ai pas
réussi à en trouver dans la norme, mais j'ai peut-être mal cherché.

Ce qui motive ces deux questions, c'est que je dois tester si une valeur
de type size_t est ou non strictement inférieure à 2^16 - 2^8. Pour
l'instant, je pense faire quelque chose comme

int is_small( size_t a )
{
if( (unsigned long) a >> 16 != 0 )
return 0;

return ((unsigned long) a + 256) >> 16 == 0;
}

pour éviter d'avoir à faire plusieurs cas selon la taille de size_t.
Cela vous paraît-il correct et portable ? Voyez-vous une façon plus
élégante/lisible de faire la même chose ?

Merci d'avance,
Manuel.

10 réponses

1 2 3
Avatar
Jean-Marc Bourguet
Manuel Pégourié-Gonnard writes:

1. La norme C89 spécifie long int, qui doit être un type entier d'au
moins 32 bits de large. Ce type est-il vraiment implémenté par tous les
compilos, y compris quand la cible est un environnement très restrei nt
(genre microcontroleur 8 bits) ?



Aucune idee sur ce point precis, mais je sais que les compilateurs pour
microp 8 bits prennent parfois plus de libertes avec la norme que les
autres.

2. A-t-on des garanties sur la taille minimum de size_t ? Je n'ai pas
réussi à en trouver dans la norme, mais j'ai peut-être mal cherché.



SIZE_MAX vaut au moins 65535 (description de stdint.h)

Ce qui motive ces deux questions, c'est que je dois tester si une valeur
de type size_t est ou non strictement inférieure à 2^16 - 2^8. Pour
l'instant, je pense faire quelque chose comme

int is_small( size_t a )
{
if( (unsigned long) a >> 16 != 0 )
return 0;

return ((unsigned long) a + 256) >> 16 == 0;
}

pour éviter d'avoir à faire plusieurs cas selon la taille de si ze_t.
Cela vous paraît-il correct et portable ? Voyez-vous une façon plus
élégante/lisible de faire la même chose ?



Quel etait le probleme avec
return a < 0xFF00;

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
espie
In article ,
Jean-Marc Bourguet wrote:
Manuel Pégourié-Gonnard writes:

1. La norme C89 spécifie long int, qui doit être un type entier d'au
moins 32 bits de large. Ce type est-il vraiment implémenté par tous les
compilos, y compris quand la cible est un environnement très restreint
(genre microcontroleur 8 bits) ?





C89, c'est un peu a la bourre, on est quand meme deux revisions plus loin.
Notons que ces points n'ont pas change sur le fond.


Aucune idee sur ce point precis, mais je sais que les compilateurs pour
microp 8 bits prennent parfois plus de libertes avec la norme que les
autres.



Un compilateur conforme doit implementer long int avec un intervalle de valeurs
correct (et donc un unsigned long int sur au moins 32 bits). Il faut voir si
on se limite aux compilateurs conformes ou pas...!

2. A-t-on des garanties sur la taille minimum de size_t ? Je n'ai pas
réussi à en trouver dans la norme, mais j'ai peut-être mal cherché.



SIZE_MAX vaut au moins 65535 (description de stdint.h)



stdint.h est C99... si Manuel cherche dans C89, c'est normal qu'il n'ait pas
trouve...

Quel etait le probleme avec
return a < 0xFF00;




Ca m'a l'air parfaitement portable pour moi aussi...
Avatar
Jean-Marc Bourguet
(Marc Espie) writes:

In article ,
Jean-Marc Bourguet wrote:
Manuel Pégourié-Gonnard writes:

1. La norme C89 spécifie long int, qui doit être un type enti er d'au
moins 32 bits de large. Ce type est-il vraiment implémenté pa r tous les
compilos, y compris quand la cible est un environnement très restr eint
(genre microcontroleur 8 bits) ?





C89, c'est un peu a la bourre, on est quand meme deux revisions plus loin.
Notons que ces points n'ont pas change sur le fond.


Aucune idee sur ce point precis, mais je sais que les compilateurs pour
microp 8 bits prennent parfois plus de libertes avec la norme que les
autres.



Un compilateur conforme doit implementer long int avec un intervalle de v aleurs
correct (et donc un unsigned long int sur au moins 32 bits). Il faut voir si
on se limite aux compilateurs conformes ou pas...!



La conformite est un moyen pour atteindre la portabilite et la
portabilite est en pratique conditionnee par bien plus que la
conformite.

Si un microp 8 bit dont le compilo est non conforme sur ce point fait
partie de mes cibles, je vais supporter son interpretation aussi peu
conforme qu'elle soit, quelles que soient les contorsions que ca
m'impose.

Si je n'ai aucune cible avec char qui n'est pas 8 bits, qui n'est pas du
complement a deux, qui n'a pas de bits de paddings, je ne vais pas
m'amuser a compliquer mon code au profit d'une conformite qui ne
m'apporte rien (je vais cependant avoir tendance a preferer une solution
ne supposant rien si elle est aussi claire qu'une autre, mais tant que
je ne peux pas tester, je ne vais pas avoir la vanite de penser que je
l'ai fait de maniere consistante).

Peut-etre plus polemique, je fais de meme les int de moins de 32 bits,
et je ne m'amuse pas avec des long dans ces cas la, utiliser long quand
j'ai des cibles ou ca fait 64 bits me poserait plus de problemes de
portabilite.

Oui je suis capable (et je m'amuse parfois) a ecrire du code conforme
qui fonctionne sur un PDP-10 avec des mots de 36 bits et des chars de 9;
mais quand je cherche une vraie portabilite vers TOPS-20 (un OS du
PDP-10), je vais y utiliser le mode non conforme qui a des char de 7
bits et un bit pas couvert par les chars dans chaque mot...

2. A-t-on des garanties sur la taille minimum de size_t ? Je n'ai pas
réussi à en trouver dans la norme, mais j'ai peut-être m al cherché.



SIZE_MAX vaut au moins 65535 (description de stdint.h)



stdint.h est C99... si Manuel cherche dans C89, c'est normal qu'il n'ait pas
trouve...

Quel etait le probleme avec
return a < 0xFF00;




Ca m'a l'air parfaitement portable pour moi aussi...



Meme si on a qqch de non conforme, si la question a du sens, il y a de
bonnes chances que ca marche.

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
Antoine Leca
Manuel Pégourié-Gonnard écrivit :
Quelques petites questions sur les types entiers :

1. La norme C89 spécifie long int, qui doit être un type entier d'au
moins 32 bits de large. Ce type est-il vraiment implémenté par tous les
compilos, y compris quand la cible est un environnement très restreint
(genre microcontroleur 8 bits) ?



Il y a deux questions entremêlées :
- le compilateur supporte-t-il long ?
- le type long fait-il au moins 32 bits ?

Un compilateur conforme doit répondre oui aux deux questions.

Mais un compilateur pour microcontrôleurs 8 bits n'est pas forcément un
compilateur conforme... et en fait, il a même pas mal de raisons de ne
pas l'être : si pour être conforme, le résultat est inutilisable sur la
cible, un vendeur de compilateur va choisir d'être utilisable, sinon à
court terme ce n'est plus un vendeur !

Maintenant, je verrais bien un compilateur limité sachant reconnaître le
type long, mais en le réduisant à 16 bits (en fait deux mots ; avec des
mots de 15 bits, cela peut même aller théoriquement à 30 bits)... Cela
permettrait de recompiler plus de logiciels (un argument très vendeur),
sans avoir des performances horribles : au détriment évidemment des
programmes qui ont réellement besoin de 32 bits...
Un tel compilateur serait donc OK pour ton idée initiale (et beaucoup
d'autres du même acabit), et ce n'est donc pas à dédaigner.

La bonne nouvelle, c'est que si le vendeur du compilateur annonce être
compatible avec la norme C89, il y a de grandes chances qu'il supporte,
au moins dans un mode spécifique, des long sur 32 bits ou plus.
En fait, si (LONG_MAX<<31)<1, c'est de la publicité mensongère.

Attention cependant, (il y a plusieurs années de cela) un certain nombre
de compilateurs annonçaient «ANSI C» dès lors qu'ils digéraient les
prototypes, toutes choses étant égales par ailleurs. Je pense que cette
espèce de présentation devrait avoir disparue, mais on est jamais trop
prudent (par exemple si tu rédiges un cahier des charges...)


2. A-t-on des garanties sur la taille minimum de size_t ? Je n'ai pas
réussi à en trouver dans la norme, mais j'ai peut-être mal cherché.



Dans la norme C89, il me semble que les discussions à l'époque disaient
que unsigned char pouvait être une implémentation conforme (et que
c'était vu comme un défaut de la norme).

Et la discussion ci-dessus s'applique de la même façon: un compilateur
pour un microcontrôleur 4 ou 8 bits avec au maximum 256 octets
adressables, pourrait faire le choix d'avoir size_t sur 8 bits...
Il ne serait pas certes pas conforme, mais pourrait fonctionner dans la
pratique pour beaucoup de programmes pas trop tordus, où un objet de
type size_t contient la taille d'un objet ou un déplacement mémoire...

Ce qui motive ces deux questions, c'est que je dois tester si une valeur
de type size_t est ou non strictement inférieure à 2^16 - 2^8.



Cf. Jean-Marc et Marc pour ce qui ne relève pas de la prise de tête.


Antoine
Avatar
Antoine Leca
Jean-Marc Bourguet écrivit :
Quel etait le probleme avec
return a < 0xFF00;



Dans les années 80, un compilo mal foutu qui interprète l'expression en
signé, et qui forcerait une conversion de a avec une valeur très grande
(>INT_MAX) vers un nombre potentiellement négatif.
À l'époque (inutile aujourd'hui), j'aurais écrit
return a < 0xFF00u;

Un des mérites de C89 (vu comme une erreur de la norme à l'époque) est
d'avoir forcé les implémentations à évoluer sur ce point, justement pour
que ce genre de code fonctionne partout. Et je pense qu'aujourd'hui, il
ne doit plus y avoir de problème.


Antoine
Avatar
espie
In article <ljolug$2d1$,
Antoine Leca wrote:

Cf. Jean-Marc et Marc pour ce qui ne relève pas de la prise de tête.



Je suis maintenant encore plus convaincu qu'il *faut* le plus possible,
le plus souvent possible eviter la prise de tete.

Le projet OpenBSD est en train de nettoyer le code d'OpenSSL, apres la
magnifique faille HeartBleed. Eh bien, c'est terrifiant tout le code
hyper-crade "refait a la main" qu'on trouve un peu partout, souvent
parce que tel compilo ante-diluvien ne supportait pas tel ou tel truc.

La ou ca pose probleme, c'est que les gars n'ont pas mis un #ifdef
autour du code a probleme, mais ils s'en sont servi sur TOUTES les
plateformes, avec comme pretexte une plateforme pourrie.

Ted Unangst a pondu un joli petit billet resume de tout ca, c'est en

http://www.tedunangst.com/flak/post/worst-common-denominator-programming

Si on pouvait eviter que ce genre de pratique se perpetue de facon
non necessaire de nos jours (genre, on sait jamais, des fois que
des gars le compilent sur un 4004), ca serait pas plus mal...
Avatar
Jean-Marc Bourguet
(Marc Espie) writes:

In article <ljolug$2d1$,
Antoine Leca wrote:

Cf. Jean-Marc et Marc pour ce qui ne relève pas de la prise de tête.



Je suis maintenant encore plus convaincu qu'il *faut* le plus possible,
le plus souvent possible eviter la prise de tete.

Le projet OpenBSD est en train de nettoyer le code d'OpenSSL, apres la
magnifique faille HeartBleed. Eh bien, c'est terrifiant tout le code
hyper-crade "refait a la main" qu'on trouve un peu partout, souvent
parce que tel compilo ante-diluvien ne supportait pas tel ou tel truc.



On parle d'autotools? ;-)

Le pire étant que bien souvent rien n'a jamais eu le problème qu'on cherche
à contourner sans avoir d'autres problèmes qu'on ne cherche pas du tout eux
à éviter. On suppose qu'on a de la mémoire à gogo, mais on va écrire en
supposant un int de 16 bits, on fait des appels systèmes propres à Linux,
mais on supporte des char de 9 bits... Il y a dans les pratiques justifées
par la portabilité (comme dans celles justifées par les performances
d'ailleurs) un aspect "cargo cult programming" certain. (Dans le genre le
bouquin de Peter Seebach sur le shell où il écrit plusieurs fois "on
accepte généralement ceci, on évite généralement cela, j'ai pas trouvé un
seul shell qui acceptait le premier sans accepter aussi le second" n'est
pas mal)

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
espie
In article ,
Jean-Marc Bourguet wrote:
On parle d'autotools? ;-)



Il y avait eu une discussion epique sur les ml gcc au moment de supprimer
le portage pour pyramid.

En gros:
A: bon, on vire le code de pyramid de la release
B: c'est pas cool d'enlever des ports comme ca, et si on gardait
A: j'ai suivi en detail les machines encore en etat de marche. C'est moi
qui possedais la derniere. Elle est morte avant-hier. Alors, on le vire
ce code ?
Avatar
Olivier Miakinen
Le 30/04/2014 09:22, Marc Espie a écrit :

A: bon, on vire le code de pyramid de la release
B: c'est pas cool d'enlever des ports comme ca, et si on gardait
A: j'ai suivi en detail les machines encore en etat de marche. C'est moi
qui possedais la derniere. Elle est morte avant-hier. Alors, on le vire
ce code ?



:-D
Avatar
Manuel Pégourié-Gonnard
Jean-Marc Bourguet scripsit :

Manuel Pégourié-Gonnard writes:

1. La norme C89 spécifie long int, qui doit être un type entier d'au
moins 32 bits de large. Ce type est-il vraiment implémenté par tous les
compilos, y compris quand la cible est un environnement très restreint
(genre microcontroleur 8 bits) ?



Aucune idee sur ce point precis, mais je sais que les compilateurs pour
microp 8 bits prennent parfois plus de libertes avec la norme que les
autres.



Ok. J'avais cette vague impression, mais sans trop savoir. Ceci dit,
pour l'instant en ce qui me concerne c'était plus une questions
théorique, a priori le code en question cible certes des plateformes
restreintes, mais pas à ce point.

2. A-t-on des garanties sur la taille minimum de size_t ? Je n'ai pas
réussi à en trouver dans la norme, mais j'ai peut-être mal cherché.



SIZE_MAX vaut au moins 65535 (description de stdint.h)



Ça m'avait échappé. Merci !

Quel etait le probleme avec
return a < 0xFF00;



Aucun. Bug mental de ma part, je me suis mélangé avec un autre truc
auquel je réfléchissais en même temps où je devais comparer avec une
valeur pas nécessairement représentable dans le plus grand type entier
de la plus petite plateforme cible, et où je procède donc par décalages
successifs pour contourner le problème.

--
1 2 3