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
Manuel Pégourié-Gonnard
Marc Espie scripsit :

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.



J'avais dans l'idée que plus on remonte loin dans les versions de
la norme, plus on a de chances que ça soit effectivement supporté
partout, d'où la référence à C89.

Par exemple, C99 spécifie long long qui doit faire au moins 64 bits de
large sauf erreur, mais j'ai reçu des plaintes d'utilisateurs chez qui
ça ne passe pas.

Manuel.
Avatar
espie
In article <lkm9oi$130h$,
Manuel Pégourié-Gonnard wrote:
Marc Espie scripsit :

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.



J'avais dans l'idée que plus on remonte loin dans les versions de
la norme, plus on a de chances que ça soit effectivement supporté
partout, d'où la référence à C89.

Par exemple, C99 spécifie long long qui doit faire au moins 64 bits de
large sauf erreur, mais j'ai reçu des plaintes d'utilisateurs chez qui
ça ne passe pas.

Manuel.



Parfois, il y a des utilisateurs qu'il faut ignorer !

Tu auras toujours quelqu'un quelque part pour essayer de compiler ton
code sur un vieux truc qui n'existe plus depuis 20 ans, avec un compilo
qui n'est plus maintenu depuis 10.

Perso, je bosse surtout sur un systeme qui n'est pas repute pour la
vitesse a laquelle il adopte les nouveautes (OpenBSD). Eh bien, on s'est
debarrasse de la derniere copie de gcc 2.95 il y a quelques mois, et c'est
le dernier compilo qui ne supportait pas les declarations n'importe ou).

Oui, on fait du C99, meme sur vax.

Sans plus de details, si tu as des utilisateurs qui ont ce genre de soucis,
il *faut* leur demander qu'est-ce qu'ils font qui fait que ca ne marche
pas...
Avatar
Manuel Pégourié-Gonnard
Antoine Leca scripsit :

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 ?



Ah oui, en effet. J'aurais eu tendance à penser que si long existait, il
faisait au moins 32 bits, mais avec tes explications je vois bien
pourquoi les vendeurs de compilos ont plutôt intérêt à faire que long
existe sans faire 32 bits, plutôt que de ne pas exister du tout.

Manuel.
Avatar
Antoine Leca
Manuel Pégourié-Gonnard écrivit :
Marc Espie scripsit :
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.



J'avais dans l'idée que plus on remonte loin dans les versions de
la norme, plus on a de chances que ça soit effectivement supporté
partout, d'où la référence à C89.



Je vois bien l'idée, mais je ne suis pas d'accord avec le raisonnement.
Celui qui a décidé de passer outre C99 et C11 n'a pas obligatoirement
vocation à être conforme à la norme C90 ; en fait, il démontre plutôt /a
priori/ qu'il n'est pas intéressé par le respect des normes ; ce qui est
en soi un problème pour toi : comme l'explique par ailleurs Marc, il y a
un moment où tu vas être obligé de mettre une barrière, probablement sur
des critères extérieurs (coûts/bénéfice ?)

Par exemple, C99 spécifie long long qui doit faire au moins 64 bits de
large sauf erreur, mais j'ai reçu des plaintes d'utilisateurs chez qui
ça ne passe pas.



Quand on analyse les raisons du non-passage de C90 à C99, on peut
repérer plusieurs cas :
- les nouveautés techniques de C99 n'étaient pas suffisantes pour
justifier les investissements ;
- la conformité à C99 implique des inconvénients réels ;
- la latence, qui s'estompe avec le temps.

Des exemples du premier cas pourrait être le cas de Microsoft, ou le cas
de nombreux projets et bibliothèques (qui ont décidés de standardiser
sur C89 plutôt que sur C99 pour pouvoir atteindre une base plus large de
« clients » ; autrement dit, la « pression du marché » eb faveur de C99
a été largement inférieure à celle de C89).

Des exemples du deuxième pourrait être le refus que long ne soit plus le
type des entiers de plus grande magnitude (pour mémoire : cet argument
fut utilise contre C99 au début, mais s'est largement estompé depuis) ;
ou la nécessité de disposer de certaines fonctionnalités «gênantes»
comme les tableaux variables ou les entiers sur 64 bits (qui gênent les
plus petites implémentations, machines 8 ou 16 bits).

Par latence, je veux dire que l'adoption d'une norme prend toujours du
temps ; beaucoup de temps : au minimum le temps que les vendeurs de
compilateurs implémentent la norme, puis (strictement séquentiel) que
les programmeurs utilisent les nouvelles versions des compilateurs. La
situation est proche de celle qui a prévalu entre Fortran 77 et Fortran
90 (et auparavant entre Fortran IV et F77). Autrement dit, la latence
est un phénomène non négligeable. Cela dit, on est maintenant en 2014,
C99 a été révisé substantiellement (et à mon sens positivement pour
faciliter les problèmes de transition) en 2011, donc on devrait
commencer à voir le bout du tunnel...

Pour revenir au cas de tes utilisateurs grognons, il faut chercher à
savoir pourquoi ils se plaignent. Et le problème « long long » -- plus
exactement le problème de la nécessité du support 64 bits, ce qui n'est
pas forcément la même chose -- est à mon sens un vrai problème, au moins
dans le marché du C pour les contrôleurs 8 et 16 bits : sachant que déjà
avec C90 la nécessité que int soit un type sur 16 bits a donné des
situations burlesques pour les contrôleurs 8 bits, on se doute que le
support de types 64 bits ne soit pas une nécessité pour les vendeurs de
compilateurs ! Et donc que les programmes « C99 » qui utilisent
aveuglement long long pour manipuler des quantités entières, histoire
d'être « le plus portable possible », vont clairement rater la cible.
Comme toujours en ingénierie, le plus important, c'est de bien définir
la cible. Et il faut que ce soit la vraie cible, pas une théorie.

On peut faire la même remarque pour tous les programmes qui, au titre de
la portabilité maximum, utilisent des techniques de programmation
défensives complexes, qui au final ne servent à rien, sauf à ralentir
très sérieusement.
Et par ailleurs la complexité sera une source de problèmes en soi.


Antoine
Avatar
espie
In article <lkq268$1ho$,
Antoine Leca wrote:
Quand on analyse les raisons du non-passage de C90 à C99, on peut
repérer plusieurs cas :
- les nouveautés techniques de C99 n'étaient pas suffisantes pour
justifier les investissements ;
- la conformité à C99 implique des inconvénients réels ;
- la latence, qui s'estompe avec le temps.

Des exemples du premier cas pourrait être le cas de Microsoft, ou le cas
de nombreux projets et bibliothèques (qui ont décidés de standardiser
sur C89 plutôt que sur C99 pour pouvoir atteindre une base plus large de
« clients » ; autrement dit, la « pression du marché » eb faveur de C99
a été largement inférieure à celle de C89).



Il convient aussi de distinguer le coeur du langage de la bibliotheque.
L'air de rien, pour la portabilite, stdint.h et inttypes.h sont de sacrees
avancees ! pas forcement tres visibles par les jeunes, mais les vieux comme
nous qui ont eu a jouer avec des typedef incompatibles entre deux bouts de
bibliotheques pour avoir des entiers de bonne taille ont accueilli cette
modif avec bonheur. Si j'etais mauvaise langue, je dirais bien que Microsoft
est LE vendeur qui n'en a eu rien a foutre, vu que la portabilite sur des
machines exotiques etait le cadet de leurs soucis (comme par hasard, maintenant
qu'ils mettent des billes dans les tablettes, ils sont les premiers a pousser
pour, par exemple, C++2014...)

Des exemples du deuxième pourrait être le refus que long ne soit plus le
type des entiers de plus grande magnitude (pour mémoire : cet argument
fut utilise contre C99 au début, mais s'est largement estompé depuis) ;
ou la nécessité de disposer de certaines fonctionnalités «gênantes»
comme les tableaux variables ou les entiers sur 64 bits (qui gênent les
plus petites implémentations, machines 8 ou 16 bits).


long long est quand meme toujours un leger souci. Il necessite de changer
le code pour que les choses soient safe, typiquement pour printf. Ca
necessite d'avoir une implementation C89, qui bossent avec les casts qui
vont bien, e.g., le tres classique printf("%lu", (unsigned long)sizeof(machin));
ou le
union {
...
long maxstorage;
}

et les idiomes C99 correspondants printf("%zu", sizeof(machin));
union {
...
intmax-t maxstorage;
}

c'est quand meme *le* truc qui casse la compatibilite ascendante. On comprend
bien que certaines personnes n'aient pas trop aime.

Bon, en pratique, l'ecrasante majorite des machines 32 bits etaient deja sur
le modele LP32, avec un type supplementaire qui supportait le 64 bits,
le plus souvent nomme quad_t sur les implementations que je connais.

C'est un domaine ou l'impact de ce changement a surtout ete theorique. Il y
a eu une periode de flottement, en pratique plus liee a l'implementation
generalisee de %z dans printf que celle de stdint.h qui est arrive tres
tres vite (essentiellement parce que les gens concernes etaient des gens
qui avaient une profonde habitude des casse-tetes de portabilite et qui
ont accueilli CE changement a bras ouvers).

Par latence, je veux dire que l'adoption d'une norme prend toujours du
temps ; beaucoup de temps : au minimum le temps que les vendeurs de
compilateurs implémentent la norme, puis (strictement séquentiel) que
les programmeurs utilisent les nouvelles versions des compilateurs. La
situation est proche de celle qui a prévalu entre Fortran 77 et Fortran
90 (et auparavant entre Fortran IV et F77). Autrement dit, la latence
est un phénomène non négligeable. Cela dit, on est maintenant en 2014,
C99 a été révisé substantiellement (et à mon sens positivement pour
faciliter les problèmes de transition) en 2011, donc on devrait
commencer à voir le bout du tunnel...



La plus grosse avancee de C11, c'est de changer le modele de description
pour prendre enfin en compte le multithread... c'est effectivement un
changement extremement positif, puisqu'on a enfin une description qui colle
avec la realite.

compilateurs ! Et donc que les programmes « C99 » qui utilisent
aveuglement long long pour manipuler des quantités entières, histoire
d'être « le plus portable possible », vont clairement rater la cible.



Des qu'on se preoccupe de taille des entiers, si on veut etre vraiment
portable, on passe par les (u)int_fastN_t et (u)int_leastN_t.

En fait, meme si c'est pas strictement dans la norme, une implementation
moderne devrait donner un stdint.h, et c'est un excellent endroit pour
signaler tous les trucs non standards.
T'as quand meme une grosse carto:
- des types entiers qui y existent;
- de la taille maximale des entiers qui peuvent etre manipules.

meme sur de l'implementation exotique sans entiers sur 64 bits, ca me
parait l'endroit ou documenter proprement ce genre de choses!
Avatar
Antoine Leca
Marc Espie écrivit :
Si j'etais mauvaise langue, je dirais bien que Microsoft
est LE vendeur qui n'en a eu rien a foutre, vu que la portabilite sur des
machines exotiques etait le cadet de leurs soucis (comme par hasard, maintenant
qu'ils mettent des billes dans les tablettes, ils sont les premiers a pousser
pour, par exemple, C++2014...)



Je ne sais pas si les tablettes sont vraiment la raison, ou alors
Microsoft a récupéré des capacités d'anticipation qui ont fait défaut
dans les années 90 ;-) Il faut aussi voir que le président du comité C++
(H. Sutter) est une pointure de l'équipe Visual C++, donc on peut
s'attendre à ce que MS soit aujourd'hui en phase avec le comité, au
moins en ce qui concerne C++.

Et c'est vrai qu'il était surprenant que pendant le développement de
C99, il n'y eut au comité C aucun représentant de Microsoft (ni des
autres compilateurs pour PC d'ailleurs), alors même que durant la
décennie précédente, ils furent des moteurs du passage au C ANSI ; à
croire que l'idéologie de l'époque était de faire crever C a.s.a.p.


La plus grosse avancee de C11, c'est de changer le modele de
description pour prendre enfin en compte le multithread... c'est
effectivement un changement extremement positif, puisqu'on a enfin
une description qui colle avec la realite.



Oui, enfin c'est le changement qui préfigure l'avenir... parce que quand
on se penche sur la liste des DR4xx (rapport de bogues concernant C11),
on voit que le texte de la norme en ce qui concerne les threads (et à
moindre titre les objets «atomiques») était plutôt du niveau de qualité
«beta», avec même des lacunes plutôt béantes (DR416) et des erreurs
(DR414, DR453) qui montrent que la relecture fut... hâtive !

http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm


Antoine
Avatar
espie
In article <lkt028$s2s$,
Antoine Leca wrote:
Marc Espie écrivit :
La plus grosse avancee de C11, c'est de changer le modele de
description pour prendre enfin en compte le multithread... c'est
effectivement un changement extremement positif, puisqu'on a enfin
une description qui colle avec la realite.



Oui, enfin c'est le changement qui préfigure l'avenir... parce que quand
on se penche sur la liste des DR4xx (rapport de bogues concernant C11),
on voit que le texte de la norme en ce qui concerne les threads (et à
moindre titre les objets «atomiques») était plutôt du niveau de qualité
«beta», avec même des lacunes plutôt béantes (DR416) et des erreurs
(DR414, DR453) qui montrent que la relecture fut... hâtive !

http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm



Je te trouve bien mechant. C'est quand meme un changement complet par
rapport a la description precedente a base de sequence point. Il eut ete
extrememement surprenant que ca soit parfait du 1e coup. On parle quand meme
de parallelisme, et ca a toujours ete un domaine ou l'esprit humain est...
defaillant.
Avatar
Antoine Leca
Marc Espie écrivit :
In article <lkt028$s2s$,
Antoine Leca wrote:
La plus grosse avancee de C11, c'est de changer le modele de
description pour prendre enfin en compte le multithread... [...]


Oui, enfin c'est le changement qui préfigure l'avenir... parce que quand
on se penche sur la liste des DR4xx (rapport de bogues concernant C11),
on voit que le texte de la norme en ce qui concerne les threads
[...] était plutôt du niveau de qualité «beta», [...]



Je te trouve bien mechant. C'est quand meme un changement complet par
rapport a la description precedente a base de sequence point. Il eut ete
extrememement surprenant que ca soit parfait du 1e coup.



Sans « être parfait », on pourrait avoir eu mieux. ÀMHA.

Je crois que le comité C11 n'a pas correctement mené la barque sur ce
coup-là. D'une part en étant trop timide au départ du processus, avec
une charte rédigée de manière très contraignante pour éviter les dérives
(ou perçues comme telles) antérieures, en particulier en interdisant
explicitement les «inventions du comité», qui a --évidemment-- été
contredit par la réalité avec à l'arrivée _Generic() ou stdatomic.h qui
y ressemble pourtant furieusement, ou une annexe K qui est suffisamment
différente de l'implémentation de référence (MSVCRT>2002) pour avoir peu
de chances de les voir converger.
Ensuite, sur le sujet précis des threads, en ne contrôlant pas le timing
et en adoptant comme texte proposé comme norme un copier-collé expurgé
(N1325, août 2008) d'une implémentation (N1287) réalisée par un membre
éminent du comité, par ailleurs portable mais pas publiée, sans prêter
suffisamment attention à des voix critiques, en particulier des
implémenteurs indépendants comme J. Navia sur comp.std.c, qui pour le
coup avait bien vu un « loup » dès 2009 (commentant N1372.pdf)...
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1325.pdf
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1287.htm
Enfin, en publiant cette nouvelle révision au pas de charge : le
processus de révision a commencé en 2008, certaines des inventions (en
particulier _Generic, N1404) ont été formalisées fin 2009,
l'avant-projet de norme a été envoyé au comité SC22 en décembre 2010, et
la norme publiée en décembre 2011... soit *avant* la cible qui était
2012 selon la charte (N1250). Pour mémoire, pour C89 l'avant projet date
de début 1986, et pour C99 l'avant projet date de 1997.


Soyons clair : je pense aussi que les threads sont une avancée majeure
pour le langage C. Mais justement pour cela, je pense que nous aurons
une révision importante de la norme sous peu, peut être vers 2016 ou
2017 (pour rester dans le cycle ISO de 5 ans, et en phase avec C++17).


Antoine
Avatar
Manuel Pégourié-Gonnard
Marc Espie scripsit :

In article <lkm9oi$130h$,
Manuel Pégourié-Gonnard wrote:
Par exemple, C99 spécifie long long qui doit faire au moins 64 bits de
large sauf erreur, mais j'ai reçu des plaintes d'utilisateurs chez qui
ça ne passe pas.



Parfois, il y a des utilisateurs qu'il faut ignorer !
[...]
Sans plus de details, si tu as des utilisateurs qui ont ce genre de soucis,
il *faut* leur demander qu'est-ce qu'ils font qui fait que ca ne marche
pas...



Je vais en effet mieux me renseigner sur ce qu'il utilise comme compilo,
s'il y a d'autres options pour sa cible, s'il ne peut pas se passer des
seuls deux modules de cette bibli qui utilisent des entiers 64 bits, et en
discuter avec le leader du projet pour voir ce qu'on en fait.

Merci pour les conseils, en tout cas !

Manuel.
Avatar
Manuel Pégourié-Gonnard
Antoine Leca scripsit :

Manuel Pégourié-Gonnard écrivit :
J'avais dans l'idée que plus on remonte loin dans les versions de
la norme, plus on a de chances que ça soit effectivement supporté
partout, d'où la référence à C89.



Je vois bien l'idée, mais je ne suis pas d'accord avec le raisonnement.
Celui qui a décidé de passer outre C99 et C11 n'a pas obligatoirement
vocation à être conforme à la norme C90 ; en fait, il démontre plutôt /a
priori/ qu'il n'est pas intéressé par le respect des normes ; ce qui est
en soi un problème pour toi : comme l'explique par ailleurs Marc, il y a
un moment où tu vas être obligé de mettre une barrière, probablement sur
des critères extérieurs (coûts/bénéfice ?)



En effet, j'avais surtout en tête ce que tu nommes plus bas la latence,
et pas trop les autres facteurs. Merci pour les explications.

Manuel.
1 2 3