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

Y a-t-il des lacunes dans la norme ISO C90 ?

61 réponses
Avatar
Fabrice
Bonjour,

Un collègue m'a posé une question à laquelle je fus incapable de
répondre : si on suit strictement la norme ISO C90 est-on garanti
d'avoir un programme portable partout ?

Par 'portable partout' j'entends que le programme compilé par n'importe
quel compilateur (respectant la norme) sur n'importe quelle architecture
donne le même résultat (aux erreurs de précision numérique et aux bugs
du compilateur près).

La véritable question est en fait de savoir si la norme est suffisante
ou bien s'il y a des lacunes dedans pour garantir qu'un programme sera
portable.

Si la norme ne suffit pas, pourriez-vous m'indiquer un sous-ensemble de
la norme pouvant garantir la portabilité ?

Merci d'avance !

10 réponses

3 4 5 6 7
Avatar
Laurent Wacrenier
Antoine Leca écrit:
Alors vous êtes sorti du cadre de la norme. Celle-ci ne s'occupe pas de
normaliser l'utilisation des sorties (ni celle des entrées, d'ailleurs).


Mais c'est dans le cadre de la question.

Avatar
Antoine Leca
En 20040415121812$, Vincent Lefevre va escriure:
Dans l'article <c5lg7q$5vd$,
Antoine Leca écrit:

On ne doit pas avoir la même manière de lire...



Je persiste.

« N'importe quel compilateur », c'est clairement à mon sens
l'obligation de ne pas dépendre du compilateur. Donc de ne pas
s'intéresser aux particularités de tel ou tel.


Non, justement s'il veut pouvoir compiler avec n'importe quel
compilateur, il faut s'intéresser aux particularités de tous
les compilateurs


Non. Il faut les fuir, au contraire !

(sous réserve que celles-ci "respectent la
norme"), tout comme il ne faut pas supposer que int, long et
long long aient telle ou telle taille (cf discussion récente
sur le fait que Microsoft utilisait des tailles particulières).


Là oui. Il faut éviter de _dépendre_ des particularités. En fait, il
*ne*faut*pas* dépendre des particularités.

Cela signifie peut-être qu'il faut savoir dans quelle mesure les
particularités de son ou de ses compilateurs sont (pardon) particulières, ou
bien si elles sont généralisables. Là d'accord. Mais on rentre dans le
processus, on est plus dans le sujet ou les résultats.


Dans la norme, c'est tellement défini à l'avance que cela l'est
avant même le début de la compilation: ce codage est « défini par
l'implémentation », ce qui signifie que le fournisseur du
compilateur est obligé de le préciser dans la documentation.


En tout cas, ce n'est pas le cas avec gcc.


Cela doit l'être, je ne penses pas que GCC C ait une telle disconformité.

Pour GCC C, cela doit dire quelque chose comme "les caractères sont encodés
suivant l'encodage utilisé pour le fichier source". Ce qui est parfaitement
défini à la compilation, même si ce n'est pas ce qu'un utilisateur peut
attendre au moment de l'exécution (mais là, c'est un autre problème).

Un cas particulier est celui des compilateurs croisés ASCII->EBCDIC (où ce
doit être omis dans la doc). Mais c'est du pinaillage. (Cependant, ce peut
être un bon mot clé pour chercher dans la doc de GCC C)


éventuellement a sur des systèmes non POSIX).


Même en dehors de POSIX, pour une implémentation (hébergée) en mode
'conforme', 'a' ne peut pas varier; sinon tu vas enfreindre certaines
contraintes (je ne me rappelle plus maintenant, mais j'ai trouvé des choses
avant-hier, c'est pour cela que je l'ai écrit).


D'accord qu'il y ait une différence si tu ne considères que le jeu de
base. Mais cela n'empêche que c'est *dépendant de l'implémentation*.
Tu obtiendras toujours un 'a', mais son code est dépend de
l'implémentation.


Je rappelle que "dépendant de l'implémentation", dans le texte de la norme,
cela sert à signaler les points où le résultat n'est pas déterministe *avec
le seul texte de la norme*, mais qu'il est *en utilisant la documentation de
l'implémentation*.

En l'occurence, il est évident que le flux d'électrons émis par HelloWorld.c
va être différent suivant si tu es sur un mainframe IBM ou un PC. Mais la
documentation de ton compilateur va te le dire. Et un 'a' sera toujours un
'a', ce n'est pas le fait que ce soit codé 0201 ou 61 (les deux seules
options pratiques) qui va rendre le programme non conforme au sens strict.


[3] Both the basic source and basic execution character sets shall
have the following members: [...]


Faut-il comprendre le "shall have" comme un "shall have only" ou un
"shall have at least". Dans la langue courante, ce serait un "shall
have at least", mais qu'en est-il de l'interprétation de la norme?


Je ne sais pas.


Antoine


Avatar
Vincent Lefevre
Dans l'article <c5mhhf$lsm$,
Antoine Leca écrit:

En 20040415121812$, Vincent Lefevre va escriure:
Non, justement s'il veut pouvoir compiler avec n'importe quel
compilateur, il faut s'intéresser aux particularités de tous
les compilateurs


Non. Il faut les fuir, au contraire !


Ah non! Cf ci-dessous.

(sous réserve que celles-ci "respectent la
norme"), tout comme il ne faut pas supposer que int, long et
long long aient telle ou telle taille (cf discussion récente
sur le fait que Microsoft utilisait des tailles particulières).


Là oui. Il faut éviter de _dépendre_ des particularités. En fait, il
*ne*faut*pas* dépendre des particularités.


Je ne parle pas de dépendre des particularités, mais de les *accepter*.

Dans la norme, c'est tellement défini à l'avance que cela l'est
avant même le début de la compilation: ce codage est « défini par
l'implémentation », ce qui signifie que le fournisseur du
compilateur est obligé de le préciser dans la documentation.


En tout cas, ce n'est pas le cas avec gcc.


Cela doit l'être, je ne penses pas que GCC C ait une telle
disconformité.


Je n'ai rien vu de tel dans la doc.

Pour GCC C, cela doit dire quelque chose comme "les caractères sont
encodés suivant l'encodage utilisé pour le fichier source".


Suivant l'encodage utilisé, on n'aura pas le même binaire, donc pas le
même comportement à l'exécution.

Je rappelle que "dépendant de l'implémentation", dans le texte de la
norme, cela sert à signaler les points où le résultat n'est pas
déterministe *avec le seul texte de la norme*, mais qu'il est *en
utilisant la documentation de l'implémentation*.


Oui.

En l'occurence, il est évident que le flux d'électrons émis par
HelloWorld.c va être différent suivant si tu es sur un mainframe IBM
ou un PC. Mais la documentation de ton compilateur va te le dire.


Elle va le dire, mais le résultat est tout de même dépendant de
l'implémentation.

Et un 'a' sera toujours un 'a', ce n'est pas le fait que ce soit
codé 0201 ou 61 (les deux seules options pratiques) qui va rendre le
programme non conforme au sens strict.


Le résultat est pourtant dépendant de l'implémentation, à moins que
tu considéres que l'encodage n'a aucune importance, ce qui est osé
(on peut au contraire vouloir des données binaires fixes). D'après

[#5] A strictly conforming program shall use only those
features of the language and library specified in this
International Standard.2) It shall not produce output
dependent on any unspecified, undefined, or implementation-
defined behavior, and shall not exceed any minimum
implementation limit.

j'en déduis que le programme n'est pas strictement conforme.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% validated (X)HTML - Acorn / RISC OS / ARM, free software, YP17,
Championnat International des Jeux Mathématiques et Logiques, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA



Avatar
Antoine Leca
En 20040415202425$, Vincent Lefevre va escriure:
Dans l'article <c5mhhf$lsm$,
Antoine Leca écrit:

Pour GCC C, cela doit dire quelque chose comme "les caractères sont
encodés suivant l'encodage utilisé pour le fichier source".


Suivant l'encodage utilisé, on n'aura pas le même binaire, donc pas le
même comportement à l'exécution.


Oui (pour les caractères hors du jeu de base). Et ce rend donc les
programmes non strictement conformes.


En l'occurence, il est évident que le flux d'électrons émis par
HelloWorld.c va être différent suivant si tu es sur un mainframe IBM
ou un PC. Mais la documentation de ton compilateur va te le dire.


Elle va le dire, mais le résultat est tout de même dépendant de
l'implémentation.


Tout dépend de ce que l'on veut spécifier. Si l'objet de la norme était de
définir le binaire (comme ce pourrait être le cas pour un assembleur), alors
oui, ce serait important. Mais nous n'en sommes pas là. C ne définit pas
quel est le flux d'électrons qui correspond à "Hello, world!". Ni même que
cela doit être des électrons, plutôt que des bananes ou des particules
d'encre apposées sur un papier. Il dit juste que ce doit être ce qui est
transmis au « dispositif de sortie ».


Et un 'a' sera toujours un 'a', ce n'est pas le fait que ce soit
codé 0201 ou 61 (les deux seules options pratiques) qui va rendre le
programme non conforme au sens strict.


Le résultat est pourtant dépendant de l'implémentation, à moins que
tu considéres que l'encodage n'a aucune importance, ce qui est osé
(on peut au contraire vouloir des données binaires fixes).


NON.
Si tu veux des données binaires fixes, tu n'écriras pas 'a', tu écrirais
'x61' ou '201', suivant les cas.
Écrivant 'a', ce que tu veux, c'est un a, au sens que cela a dans ton
contexte. Et la norme te garantit donc que c'est ce qui va sortir, à
condition de ne faire de sortie qu'en utilisant les spécificateurs %c et %s,
ou bien fputc(). Exclusivement.

Et comme on l'a bien compris, la norme ne peux pas garantir la même chose
pour 'é', donc cette dernière constante ne peux pas être utilisée dans un
programme strictement conforme, ni d'ailleurs pour 'u00E9', ce qui annule
une grande partie de l'intérêt de cette dernière notation.


Antoine


Avatar
Vincent Lefevre
Dans l'article <c5oj9o$l05$,
Antoine Leca écrit:

En 20040415202425$, Vincent Lefevre va escriure:
Dans l'article <c5mhhf$lsm$,
Antoine Leca écrit:

Pour GCC C, cela doit dire quelque chose comme "les caractères sont
encodés suivant l'encodage utilisé pour le fichier source".


Suivant l'encodage utilisé, on n'aura pas le même binaire, donc pas le
même comportement à l'exécution.


Oui (pour les caractères hors du jeu de base). Et ce rend donc les
programmes non strictement conformes.


Même pour les caractères du jeu de base.

Si tu veux des données binaires fixes, tu n'écriras pas 'a', tu écrirais
'x61' ou '201', suivant les cas.


Cela tombe sous le sens. Mais ce n'est pas explicitement dit par la
norme. Imagine qu'un programmeur veuille générer un caractère 'a' pour
l'implémentation (de manière portable), compile son programme. Puis il
décide plus tard d'utiliser le résultat dans un contexte où le jeu de
caractères est basé sur l'ASCII. Suivant les implémentations, on aura
bien des différences, et le programme est non strictement conforme.

La norme ne présuppose pas que ce que le programmeur a écrit est
exactement ce qu'il veut. En particulier, si le programmeur écrit
'a', la norme ne présuppose pas que le programmeur veut un 'a' en
sortie sans s'intéresser à l'encodage. Si le programmeur veut un
encodage particulier alors qu'il utilise 'a', appelle ça un bug
si tu veux, mais la notion de bug est orthogonale à la notion de
(stricte) conformité.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% validated (X)HTML - Acorn / RISC OS / ARM, free software, YP17,
Championnat International des Jeux Mathématiques et Logiques, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA



Avatar
Antoine Leca
En 20040416165446$, Vincent Lefevre va escriure:
Oui (pour les caractères hors du jeu de base). Et ce rend donc les
programmes non strictement conformes.


Même pour les caractères du jeu de base.


Pas d'accord.
Prenons une chaîne de spécifications de fprintf. Elle est définie par des
constantes caractères. Qui sont stockées dans le binaire (et on ne peut
envisager un mécanisme spécifique, puisque c'est un argument comme les
autres, il peut être variable).
Le seul effet qui peut affecter, ce sont les locales, et en particulier
LC_CTYPE, d'accord ? Qui dépend exclusivement de setlocale(). Or que dit la
description de setlocale(): "LC_CTYPE affects the behavior of the character
handling functions* and the multibyte and wide character functions."
[7.11.1.1] Donc cela ne doit pas affecter fprintf.

Le lecteur un peu tordu va alors remarquer que l'argument de fprintf est une
chaîne de multibyte: "The format shall be a multibyte character sequence,
beginning and ending in its initial shift state. The format is composed of
zero or more directives: ordinary multibyte characters (not %), which are
copied unchanged to the output stream; and conversion specifications, each
of which results in fetching zero or more subsequent arguments, converting
them, if applicable, according to the corresponding conversion specifier,
and then writing the result to the output stream."

Il n'est donc pas clair si les composants de spécification de conversion
peuvent être des élements du jeu étendu, ou ce sont des éléments du jeu de
base: il s'en est même trouvé un, de tordu, pour poser la question au
comité. Qui s'est fendu d'une réponse:
<URL:http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/dr_090.html>.

Autrement dit, les éléments de la chaîne de format sont intangibles. Et par
extension, les valeurs des éléments du jeu de caractères de base n'ont aucun
moyen de varier.

Si tu veux des données binaires fixes, tu n'écriras pas 'a', tu
écrirais 'x61' ou '201', suivant les cas.


Cela tombe sous le sens. Mais ce n'est pas explicitement dit par la
norme.


Ah non ? Et où la norme expliquerait le contraire ?

Parce que les normes ISO disent bien clairement que ce qui n'est pas défini
explicitement doit être compris avec l'acceptation commune (du OED pour le
sens des mots). Donc si cela tombe sous le sens, et que la norme ne dit pas
le contraire, c'est comme cela qu'il faut faire, et pas inventer autre
chose.


Imagine qu'un programmeur veuille générer un caractère 'a' pour
l'implémentation (de manière portable), compile son programme. Puis il
décide plus tard d'utiliser le résultat dans un contexte où le jeu de
caractères est basé sur l'ASCII. Suivant les implémentations, on aura
bien des différences, et le programme est non strictement conforme.


Je n'ai toujours pas compris pourquoi il y aurait des différences.
Soit il a compilé pour une cible ASCII. Le programme focntionne, et
fonctionne toujours de la même manière. Aucune différence.
Soit il a compilé pour une cible EBCDIC. Clairement, s'il utilise le binaire
sur une machine qui marche en ASCII, il n'a pas utilisé un enviroenement de
compilation conforme, c'est tout. Parce que en l'occurence, RIEN ne marche.

C'est un peu comme si tu compiles sur Windows NT avec l'API Unicode (les
fonctions de l'OS sont terminées par un W), et que essayes de lancer le
programme en liant les appels de l'OS aux versions ANSI (fonctions terminées
avec un A). Cela ne peut pas fonctionner, mais la seule chose que cela
démontre, c'est que ce procédé ne donne pas un "compilateur" conforme.


La norme ne présuppose pas que ce que le programmeur a écrit est
exactement ce qu'il veut.


D'accord.

En particulier, si le programmeur écrit
'a', la norme ne présuppose pas que le programmeur veut un 'a' en
sortie sans s'intéresser à l'encodage.


Si. Parce que la norme ne définit à aucun endroit cet encodage (sauf pour
les chiffres décimaux). Elle ne définit que des propriétés minimales de cet
encodage, comme le fait qu'il doit être entre 1 et CHAR_MAX, ou l'effet des
"format effectors".

Si le programmeur veut un
encodage particulier alors qu'il utilise 'a'


... alors il n'utilise pas le bon outil ! La norme ne lui donne pas cette
possibilité, c'est tout. Ou plus exactement, son programme n'est _plus_
strictement conforme.

(Et je me répète, dans la pratique ce n'est pas un problème, puisque ce ne
peut être que 'x61' ou '201'. Au pire cela coûte deux tableaux de 256
entrées. Tandis qu'il est beaucoup plus important de s'affranchir du contenu
à la fois des sources et des binaires, et de garantir que "Hello, world!"
s'affiche bien, que tu sois sur une machine ASCII ou sur une machine EBCDIC.
Ce, sans modifier le source, gravé dans la matrice du K&R1. Mieux encore, un
source avec un texte en japonais, sans être strictement conforme parce que
dépendant du locale, va quand même fonctionner correctement, indépendament
des codages utilisés; tandis que le programmeur qui s'intéresse à forcer les
encodages des kanji, lui, va devoir se trimballer des tables de plusieurs
centaines de milliers d'entrées. Qui n'intéresse personne dans la réalité.)


Antoine


Avatar
Vincent Lefevre
Dans l'article <c5pd47$4g5$,
Antoine Leca écrit:

En 20040416165446$, Vincent Lefevre va escriure:
Oui (pour les caractères hors du jeu de base). Et ce rend donc les
programmes non strictement conformes.


Même pour les caractères du jeu de base.


Pas d'accord.
Prenons une chaîne de spécifications de fprintf. Elle est définie par des
constantes caractères. Qui sont stockées dans le binaire (et on ne peut
envisager un mécanisme spécifique, puisque c'est un argument comme les
autres, il peut être variable).


Attention, je ne considère pas un binaire fixé, mais des binaires
générés par des implémentations différentes. Les caractères en
sortie seront les mêmes (pour le jeu de base), mais pas les codes
(on peut avoir de l'ASCII, de l'EBCDIC ou autre chose suivant
l'implémentation).

[snip la suite -- de toute façon, setlocale() est fortement dépendant
de l'implémentation, non?]

Si tu veux des données binaires fixes, tu n'écriras pas 'a', tu
écrirais 'x61' ou '201', suivant les cas.


Cela tombe sous le sens. Mais ce n'est pas explicitement dit par la
norme.


Ah non ? Et où la norme expliquerait le contraire ?


Je n'ai jamais dit qu'elle explique le contraire.

Parce que les normes ISO disent bien clairement que ce qui n'est pas
défini explicitement doit être compris avec l'acceptation commune
(du OED pour le sens des mots). Donc si cela tombe sous le sens, et
que la norme ne dit pas le contraire, c'est comme cela qu'il faut
faire, et pas inventer autre chose.


Tu ne fais pas avancer les choses. Ça tombe aussi sous le sens de ne
pas écrire des programmes buggés. Ce n'est pas pour autant que les
programmes buggés sont forcément non conformes.

Imagine qu'un programmeur veuille générer un caractère 'a' pour
l'implémentation (de manière portable), compile son programme. Puis il
décide plus tard d'utiliser le résultat dans un contexte où le jeu de
caractères est basé sur l'ASCII. Suivant les implémentations, on aura
bien des différences, et le programme est non strictement conforme.


Je n'ai toujours pas compris pourquoi il y aurait des différences.
Soit il a compilé pour une cible ASCII. Le programme focntionne, et
fonctionne toujours de la même manière. Aucune différence.
Soit il a compilé pour une cible EBCDIC. Clairement, s'il utilise le binaire
sur une machine qui marche en ASCII, il n'a pas utilisé un enviroenement de
compilation conforme, c'est tout. Parce que en l'occurence, RIEN ne marche.


Pas d'accord. On peut très bien manipuler de l'EBCDIC dans un
environnement d'exécution utilisant de l'ASCII. Ce que j'entends
par là, c'est qu'on peut très bien vouloir manipuler des codes
binaires alors qu'initialement on manipulait des caractères.

La norme ne présuppose pas que ce que le programmeur a écrit est
exactement ce qu'il veut.


D'accord.

En particulier, si le programmeur écrit 'a', la norme ne
présuppose pas que le programmeur veut un 'a' en sortie sans
s'intéresser à l'encodage.


Si. Parce que la norme ne définit à aucun endroit cet encodage (sauf
pour les chiffres décimaux). Elle ne définit que des propriétés
minimales de cet encodage, comme le fait qu'il doit être entre 1 et
CHAR_MAX, ou l'effet des "format effectors".


Et alors? Je ne suis pas du tout d'accord avec ton argumentation.
Voici un exemple *utile* montrant qu'on peut très bien utiliser 'a'
à la fois sous la forme caractère et sous la forme numérique:

#include <stdio.h>
int main(void)
{
int c = 'a';
printf("Code de '%c' = %dn", c, c);
return 0;
}

J'espère que cela te convaincra.

Si le programmeur veut un
encodage particulier alors qu'il utilise 'a'


... alors il n'utilise pas le bon outil ! La norme ne lui donne pas cette
possibilité, c'est tout. Ou plus exactement, son programme n'est _plus_
strictement conforme.


Non, cela peut également être un bug.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% validated (X)HTML - Acorn / RISC OS / ARM, free software, YP17,
Championnat International des Jeux Mathématiques et Logiques, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA



Avatar
Antoine Leca
En 20040416204456$, Vincent Lefevre va escriure:
Attention, je ne considère pas un binaire fixé, mais des binaires
générés par des implémentations différentes. Les caractères en
sortie seront les mêmes (pour le jeu de base), mais pas les codes
(on peut avoir de l'ASCII, de l'EBCDIC ou autre chose suivant
l'implémentation).


J'avais bien compris.
Ce que je dis, c'est que ce qui importe, ce n'est pas le contenu du binaire
pour une plateforme donnée (qui ne fait pas partie de ce que définit la
norme), mais la signification de la suite de multiplets codée dans ce
binaire, qui doivent être les caractères (du jeu de base), '%', 's', etc.,
pour que printf puisse fonctionner. Donc l'interprétation de ces codes
binaires doit être univoque.

Le programme strictement conforme ne peut pas tirer profit des valeurs
réelles de ces codes, juste du fait qu'ils existent et qu'ils sont
distincts. C'est comme avec INT_MAX: un programme portable peut utiliser
cette valeur, par exemple pour faire des optimisations (utiliser des int au
lieu de long pour des quantités 32 bits sur un plateforme donnée), mais ne
peut pas afficher la valeur de cette constante.

Par contre, le programme strictement conforme peut utiliser la propriété de
leur sighnification en tant que lettres de l'alphabet latin ou symboles de
ponctuation. Sans cesser d'être strictement conforme,


Pas d'accord. On peut très bien manipuler de l'EBCDIC dans un
environnement d'exécution utilisant de l'ASCII.


Oui. Mais à moins d'utiliser un compilateur croisé (auquel cas tu ne
manipules que de l'EBCDIC, le fait que l'hôte soit ASCII est juste
anecdotique, un peu comme si tu compilais pour une machine de Turing), tu ne
peux pas attendre que "Hello %sn" servent à la fois comme chaîne de
spécifications pour printf() (qui attends donc de l'ASCII) et en même temps
comme données transmises/manipulées par le programme (qui doivent être en
EBCDIC). En fait, soit tu choisis la deuxième interprétation, et de fait tu
as un compilateur croisé (donc impossible à exécuter sur la machine
hôte); soit tu choisis la première, cas normal, et alors l'EBCDIC, tu es
obligé de l'encoder « à la main », exactement ce que font tous ceux qui
écrivent des outils croisés.


Ce que j'entends
par là, c'est qu'on peut très bien vouloir manipuler des codes
binaires alors qu'initialement on manipulait des caractères.


Oui. Et la seule manière de le faire en C (strictement conforme), c'est
d'abandonner les constantes caractères (ou chaînes). Le fait que ce ne soit
pas la pratique, démontre seulement qu'à peu près personne ne cherche à le
faire.


En particulier, si le programmeur écrit 'a', la norme ne
présuppose pas que le programmeur veut un 'a' en sortie sans
s'intéresser à l'encodage.


Si. Parce que la norme ne définit à aucun endroit cet encodage (sauf
pour les chiffres décimaux). Elle ne définit que des propriétés
minimales de cet encodage, comme le fait qu'il doit être entre 1 et
CHAR_MAX, ou l'effet des "format effectors".


Et alors? Je ne suis pas du tout d'accord avec ton argumentation.
Voici un exemple *utile* montrant qu'on peut très bien utiliser 'a'
à la fois sous la forme caractère et sous la forme numérique:

#include <stdio.h>
int main(void)
{
int c = 'a';
printf("Code de '%c' = %dn", c, c);
return 0;
}

J'espère que cela te convaincra.


De quoi devrais-je être convaincu ?

La seule chose qui est claire pour moi, c'est que cet exemple n'est pas
strictement conforme.

Bien sûr, il aurait pu l'être, parce que c'est un programme utile, aucun
doute là-dessus dans mon esprit; le choix du comité fut différent, parce
qu'il fallut bien tracer la ligne quelque part.

De même,

#include <stdio.h>
#include <limits.h>
int main(void) {
int b=0;
unsigned u=UINT_MAX;

while( u ) ++b, u>>=1;
printf("Nombre de bits dans un entier: %dn", b);
return 0;
}

Peut-être utile, mais ne sera jamais strictement conforme.

On peut se plaindre qu'il manque un nom à la notion de programmes qui
n'utilisent que des constructions définies (éventuellement par
l'implémentation, éventuellement non spécifiées). On pourrait dire, d'après
l'exposé des motifs, que ce sont "les programmes C", mais ce n'est pas dit
comme cela.
Et ce sont pourtant les plus intéressants.


Antoine



Avatar
Vincent Lefevre
Dans l'article <c62v7i$t6q$,
Antoine Leca écrit:

Ce que je dis, c'est que ce qui importe, ce n'est pas le contenu du binaire
pour une plateforme donnée (qui ne fait pas partie de ce que définit la
norme), mais la signification de la suite de multiplets codée dans ce
binaire, qui doivent être les caractères (du jeu de base), '%', 's', etc.,


Je pense que c'est notre point de désaccord. Je ne vois pas pourquoi
le contenu du binaire ne serait pas important (pour l'ensemble des
applications possibles) et ne devrait donc pas être pris en compte.
Le fait que la norme ne définit pas ces codes binaires n'est pas une
bonne raison (c'est bien pour ça que je dis que c'est dépendant de
l'implémentation, tout comme certains autres comportements, e.g. les
valeurs limites).

Le programme strictement conforme ne peut pas tirer profit des valeurs
réelles de ces codes, juste du fait qu'ils existent et qu'ils sont
distincts. C'est comme avec INT_MAX: un programme portable peut utiliser
cette valeur, par exemple pour faire des optimisations (utiliser des int au
lieu de long pour des quantités 32 bits sur un plateforme donnée), mais ne
peut pas afficher la valeur de cette constante.


Juste pour savoir... En admettant ton interprétation, est-ce que le
programme suivant est strictement conforme?

#include <stdio.h>
int main(void)
{
printf ("%dn", INT_MAX == 32767 ? INT_MAX : 32767);
return 0;
}

Ce que j'entends par là, c'est qu'on peut très bien vouloir
manipuler des codes binaires alors qu'initialement on manipulait
des caractères.


Oui. Et la seule manière de le faire en C (strictement conforme),
c'est d'abandonner les constantes caractères (ou chaînes). Le fait
que ce ne soit pas la pratique, démontre seulement qu'à peu près
personne ne cherche à le faire.


Mais pourtant ces codes binaires auront une interprétation différente
suivant les implémentation. Donc pourquoi serait-ce strictement
conforme?

Et alors? Je ne suis pas du tout d'accord avec ton argumentation.
Voici un exemple *utile* montrant qu'on peut très bien utiliser 'a'
à la fois sous la forme caractère et sous la forme numérique:

#include <stdio.h>
int main(void)
{
int c = 'a';
printf("Code de '%c' = %dn", c, c);
return 0;
}

J'espère que cela te convaincra.


De quoi devrais-je être convaincu ?

La seule chose qui est claire pour moi, c'est que cet exemple n'est pas
strictement conforme.


Pourquoi dis-tu cela sur ce programme alors que tu réfutes l'utilisation
des codes binaires plus haut?

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% validated (X)HTML - Acorn / RISC OS / ARM, free software, YP17,
Championnat International des Jeux Mathématiques et Logiques, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA


Avatar
Antoine Leca
En 20040420115004$, Vincent Lefevre va escriure:
Dans l'article <c62v7i$t6q$,
Antoine Leca écrit:

Ce que je dis, c'est que ce qui importe, ce n'est pas le contenu du
binaire pour une plateforme donnée (qui ne fait pas partie de ce que
définit la norme), mais la signification de la suite de multiplets
codée dans ce binaire, qui doivent être les caractères (du jeu de
base), '%', 's', etc.,


Je pense que c'est notre point de désaccord. Je ne vois pas pourquoi
le contenu du binaire ne serait pas important (pour l'ensemble des
applications possibles) et ne devrait donc pas être pris en compte.


Au moins, on a trouvé ce sur quoi nous différons !


Juste pour savoir... En admettant ton interprétation, est-ce que le
programme suivant est strictement conforme?

#include <stdio.h>
int main(void)
{
printf ("%dn", INT_MAX == 32767 ? INT_MAX : 32767);
return 0;
}


En supposant bien sûr que tu #inclus <limits.h>, à mon sens, oui : il
produit toujours "32767n", donc peut être réduit à
int main() { puts("32767"); return 0;}
C'est juste une variante de HelloWorld.c, et l'idée c'est bien que ce
programme-là, au moins, soit strictement conforme. Je sers du fait que c'est
le résultat qui compte, pas la manière d'y arriver. Donc pour reprendre ton
exemple,

#include <stdio.h>
#include <limits.h>
int main(void) {
int c = 'a';
char s[CHAR_BIT/3 + 17];
sprintf(s, "Code de '%c' = %dn", c, c);
return 0;
}

est, à mon sens, strictement conforme. Y compris si on rajoute un appel à
setlocale(LC_CTYPE, "");.

[ En fait, il ne l'est pas, parce que, théoriquement, CHAR_BIT peut être
très grand, et alors soit s va passer la limite de 32767/65535, soit le %d
va dépasser la limite de 509/4095. Mais bon. ]



Mais pourtant ces codes binaires auront une interprétation différente
suivant les implémentation. Donc pourquoi serait-ce strictement
conforme?


Justement, c'est là le point: si tu interprètes les codes binaires, tu sors
de la conformité stricte.
La seule chose que tu puisses faire avec les constantes caractères, c'est
les balader deci-delà, et à la fin les sortir sur la sortie standard. Les
autres opérations, à l'exception de comparer avec 0 et de faire des
additions ou des soustractions de quantités inférieures à 10 quand tu sais
que ce sont des chiffres, te font sortir de la portabilité.


De quoi devrais-je être convaincu ?

La seule chose qui est claire pour moi, c'est que cet exemple n'est
pas strictement conforme.


Pourquoi dis-tu cela sur ce programme alors que tu réfutes
l'utilisation des codes binaires plus haut?


Je ne la réfute pas, je dis que le fait de les utiliser rend le programme
non conforme de manière stricte, autrement dit pas totalement portable.
Parce que avec ton programme, une machine ASCII va donner
Code de 'a' = 97<NL>
Et une machine EBCDIC
Code de 'a' = 129<NL>
Ce qui n'est pas la même chose, donc le programme n'a pas le même effet sur
deux machines différentes, donc il n'est pas portable au sens où l'effet du
programme doit être identique. Comme tu le dis, il reste intéressant, en
particulier pour celui qui s'intéresse aux représentations des caractères
sur la machine cible. Mais ce sujet-là, explicitement, n'est pas couvert par
la norme C.


Antoine


3 4 5 6 7