En cmctic$7ft$, Charlie Gordon va escriure:A ce propos, je me souviens avoir optimisé en 1991 à Cambridge le
driver Postscript de Lotus 1-2-3.
Jolie anecdote.plus de 90% du temps passé était concentré dans une seule routine qui
convertissait en chaines de caractères en base 10 des nombres entiers
Tu ramènes de l'eau à mon moulin, là: par rapport à itoa qui est censé gérer
toutes les bases, sprintf est «prévenu» de la base à utiliser, donc peut
optimiser à part la base 10 (ou 16).
;-)
Après, c'est un problème de qualité d'implémentation: c'est évident que si
tu as un problème de perf' et que la routine de conversion numérique vers
texte intégrée dans xprintf() fait la division « à la main » (et si en plus
elle doit gérer les objets sur 64 ou 128 bits avec le même chemin... sans
commentaire)pour la plupart constants.
Tu as des chiffres sur l'impact de traiter à part les constantes (courantes)
? Je suppose que ce doit être important, mais les faits sont meilleurs que
les suppositions...
En cmctic$7ft$1@reader1.imaginet.fr, Charlie Gordon va escriure:
A ce propos, je me souviens avoir optimisé en 1991 à Cambridge le
driver Postscript de Lotus 1-2-3.
Jolie anecdote.
plus de 90% du temps passé était concentré dans une seule routine qui
convertissait en chaines de caractères en base 10 des nombres entiers
Tu ramènes de l'eau à mon moulin, là: par rapport à itoa qui est censé gérer
toutes les bases, sprintf est «prévenu» de la base à utiliser, donc peut
optimiser à part la base 10 (ou 16).
;-)
Après, c'est un problème de qualité d'implémentation: c'est évident que si
tu as un problème de perf' et que la routine de conversion numérique vers
texte intégrée dans xprintf() fait la division « à la main » (et si en plus
elle doit gérer les objets sur 64 ou 128 bits avec le même chemin... sans
commentaire)
pour la plupart constants.
Tu as des chiffres sur l'impact de traiter à part les constantes (courantes)
? Je suppose que ce doit être important, mais les faits sont meilleurs que
les suppositions...
En cmctic$7ft$, Charlie Gordon va escriure:A ce propos, je me souviens avoir optimisé en 1991 à Cambridge le
driver Postscript de Lotus 1-2-3.
Jolie anecdote.plus de 90% du temps passé était concentré dans une seule routine qui
convertissait en chaines de caractères en base 10 des nombres entiers
Tu ramènes de l'eau à mon moulin, là: par rapport à itoa qui est censé gérer
toutes les bases, sprintf est «prévenu» de la base à utiliser, donc peut
optimiser à part la base 10 (ou 16).
;-)
Après, c'est un problème de qualité d'implémentation: c'est évident que si
tu as un problème de perf' et que la routine de conversion numérique vers
texte intégrée dans xprintf() fait la division « à la main » (et si en plus
elle doit gérer les objets sur 64 ou 128 bits avec le même chemin... sans
commentaire)pour la plupart constants.
Tu as des chiffres sur l'impact de traiter à part les constantes (courantes)
? Je suppose que ce doit être important, mais les faits sont meilleurs que
les suppositions...
avec une syntaxe
(snprintf) qui n'a rien a voir et qui n'est pas sans pièges.
Si tu passes tous les paramètres équivalents à ceux de strtol à _ltostr,
plus ceux pour gérer la chaîne et son allocation, tu va finir avec une
syntaxe plutôt lourde, tu ne crois pas ?
Par exemple putc(c,fp) me semble plus efficace que fprintf(fp, "%c", c);
Oui. Et je me demande ce qu'il en est pour puts("ma chaine:", fp),
puts(chaine, fp), putc('n', fp); par rapport au fprintf équivalent.
Mais cela n'a pas grand chose à voir avec le sujet.
Ce qui est regrettable dans itoa, c'est que la taille du tableau
résultat n'est pas spécifiée dans l'appel, avec les problèmes de
débordement de tableaux que cela peut poser si le programmeur est peu
méfiant ou que la taille des types entiers change au delà de ses
attentes.
Ça, c'est l'argument massue pour ne PAS normaliser itoa(). gets()a réussi à
rester parce qu'il y avait à côté un moyen simple d'éviter les débordements.
En ce qui concerne le itoa() classique (issu de MS-DOS je pense), cet
équivalent simple n'existe pas, ou plutôt on en revient à sprintf() et un
calcul de la longueur de la chaîne en fonction des propriétés des types
entiers; et quand tu en es là, utiliser sprintf ou autre chose devient
anecdotique, sans parler de la lourdeur.
Et je ne vois pas en quoi itoa() peut-être plus efficace vu que les
opérations utilisées seront les mêmes que snprintf() à part
l'allocation mémoire initiale de itoa().
parce que snprintf finira par appeler la fonction que je me propose
d'appeler directement.
Chez moi, cette fonction est snprintf elle-même (en fait, vfprintf avec un
FILE spécial).
[...]
d'un autre côté tu vas trouver des implémentations de
itoa() qui appelent sprintf() ;-) (de la même manière qu'aujourd'hui, c'est
en général vain d'essayer de gagner du temps en utilisant atoi())
Si tu es vraiment juste sur les perfs de cette partie, tu ne vas pas couper
de réécrire cela toi-même.
Enfin, par expérience les programmes qui génèrent des chaînes de caractères
ne le font pas pour faire joli, ils finissent par ranger ces chaînes quelque
part, dans un fichier ou dans un socket, donc ils finissent par être limités
par le débit des entrées-sorties (OK, cela fait un bail que je n'ai pas
programmé sur un processeur plus lent que son contrôleur d'E/S, même si je
sais que cela existe encore, surtout en C).
Pour finir, la vraie raison, c'est que itoa() n'existait pas sur les bécanes
Unix (plus précisement, sur V7).
avec une syntaxe
(snprintf) qui n'a rien a voir et qui n'est pas sans pièges.
Si tu passes tous les paramètres équivalents à ceux de strtol à _ltostr,
plus ceux pour gérer la chaîne et son allocation, tu va finir avec une
syntaxe plutôt lourde, tu ne crois pas ?
Par exemple putc(c,fp) me semble plus efficace que fprintf(fp, "%c", c);
Oui. Et je me demande ce qu'il en est pour puts("ma chaine:", fp),
puts(chaine, fp), putc('n', fp); par rapport au fprintf équivalent.
Mais cela n'a pas grand chose à voir avec le sujet.
Ce qui est regrettable dans itoa, c'est que la taille du tableau
résultat n'est pas spécifiée dans l'appel, avec les problèmes de
débordement de tableaux que cela peut poser si le programmeur est peu
méfiant ou que la taille des types entiers change au delà de ses
attentes.
Ça, c'est l'argument massue pour ne PAS normaliser itoa(). gets()a réussi à
rester parce qu'il y avait à côté un moyen simple d'éviter les débordements.
En ce qui concerne le itoa() classique (issu de MS-DOS je pense), cet
équivalent simple n'existe pas, ou plutôt on en revient à sprintf() et un
calcul de la longueur de la chaîne en fonction des propriétés des types
entiers; et quand tu en es là, utiliser sprintf ou autre chose devient
anecdotique, sans parler de la lourdeur.
Et je ne vois pas en quoi itoa() peut-être plus efficace vu que les
opérations utilisées seront les mêmes que snprintf() à part
l'allocation mémoire initiale de itoa().
parce que snprintf finira par appeler la fonction que je me propose
d'appeler directement.
Chez moi, cette fonction est snprintf elle-même (en fait, vfprintf avec un
FILE spécial).
[...]
d'un autre côté tu vas trouver des implémentations de
itoa() qui appelent sprintf() ;-) (de la même manière qu'aujourd'hui, c'est
en général vain d'essayer de gagner du temps en utilisant atoi())
Si tu es vraiment juste sur les perfs de cette partie, tu ne vas pas couper
de réécrire cela toi-même.
Enfin, par expérience les programmes qui génèrent des chaînes de caractères
ne le font pas pour faire joli, ils finissent par ranger ces chaînes quelque
part, dans un fichier ou dans un socket, donc ils finissent par être limités
par le débit des entrées-sorties (OK, cela fait un bail que je n'ai pas
programmé sur un processeur plus lent que son contrôleur d'E/S, même si je
sais que cela existe encore, surtout en C).
Pour finir, la vraie raison, c'est que itoa() n'existait pas sur les bécanes
Unix (plus précisement, sur V7).
avec une syntaxe
(snprintf) qui n'a rien a voir et qui n'est pas sans pièges.
Si tu passes tous les paramètres équivalents à ceux de strtol à _ltostr,
plus ceux pour gérer la chaîne et son allocation, tu va finir avec une
syntaxe plutôt lourde, tu ne crois pas ?
Par exemple putc(c,fp) me semble plus efficace que fprintf(fp, "%c", c);
Oui. Et je me demande ce qu'il en est pour puts("ma chaine:", fp),
puts(chaine, fp), putc('n', fp); par rapport au fprintf équivalent.
Mais cela n'a pas grand chose à voir avec le sujet.
Ce qui est regrettable dans itoa, c'est que la taille du tableau
résultat n'est pas spécifiée dans l'appel, avec les problèmes de
débordement de tableaux que cela peut poser si le programmeur est peu
méfiant ou que la taille des types entiers change au delà de ses
attentes.
Ça, c'est l'argument massue pour ne PAS normaliser itoa(). gets()a réussi à
rester parce qu'il y avait à côté un moyen simple d'éviter les débordements.
En ce qui concerne le itoa() classique (issu de MS-DOS je pense), cet
équivalent simple n'existe pas, ou plutôt on en revient à sprintf() et un
calcul de la longueur de la chaîne en fonction des propriétés des types
entiers; et quand tu en es là, utiliser sprintf ou autre chose devient
anecdotique, sans parler de la lourdeur.
Et je ne vois pas en quoi itoa() peut-être plus efficace vu que les
opérations utilisées seront les mêmes que snprintf() à part
l'allocation mémoire initiale de itoa().
parce que snprintf finira par appeler la fonction que je me propose
d'appeler directement.
Chez moi, cette fonction est snprintf elle-même (en fait, vfprintf avec un
FILE spécial).
[...]
d'un autre côté tu vas trouver des implémentations de
itoa() qui appelent sprintf() ;-) (de la même manière qu'aujourd'hui, c'est
en général vain d'essayer de gagner du temps en utilisant atoi())
Si tu es vraiment juste sur les perfs de cette partie, tu ne vas pas couper
de réécrire cela toi-même.
Enfin, par expérience les programmes qui génèrent des chaînes de caractères
ne le font pas pour faire joli, ils finissent par ranger ces chaînes quelque
part, dans un fichier ou dans un socket, donc ils finissent par être limités
par le débit des entrées-sorties (OK, cela fait un bail que je n'ai pas
programmé sur un processeur plus lent que son contrôleur d'E/S, même si je
sais que cela existe encore, surtout en C).
Pour finir, la vraie raison, c'est que itoa() n'existait pas sur les bécanes
Unix (plus précisement, sur V7).
"Charlie Gordon" writes:
[...]
| > En ce qui concerne le itoa() classique (issu de MS-DOS je pense), cet
| > équivalent simple n'existe pas, ou plutôt on en revient à sprintf() et un
| > calcul de la longueur de la chaîne en fonction des propriétés des types
| > entiers; et quand tu en es là, utiliser sprintf ou autre chose devient
| > anecdotique, sans parler de la lourdeur.
|
| Je ne crois pas que cet argument tienne : le fait qu'il existait déjà à
l'époque
| une alternative correcte à gets(), en l'occurrence fgets() est la raison qui
| aurait dû conduire à exclure gets() de la norme ANSI.
Je crois que tu fais l'erreur colossale de croire que la norme était
écrite pour ne contenir que des choses « non bugguées ».
Certains aiment à dire que la charte du comité ANSI était de codifier
la partique existante, alors ... -- mais, en réalité c'est pas vrai,
le comité a fait mal d'inventions, y compris l'infame void* -> T*
et volatile.
"Charlie Gordon" <news@chqrlie.org> writes:
[...]
| > En ce qui concerne le itoa() classique (issu de MS-DOS je pense), cet
| > équivalent simple n'existe pas, ou plutôt on en revient à sprintf() et un
| > calcul de la longueur de la chaîne en fonction des propriétés des types
| > entiers; et quand tu en es là, utiliser sprintf ou autre chose devient
| > anecdotique, sans parler de la lourdeur.
|
| Je ne crois pas que cet argument tienne : le fait qu'il existait déjà à
l'époque
| une alternative correcte à gets(), en l'occurrence fgets() est la raison qui
| aurait dû conduire à exclure gets() de la norme ANSI.
Je crois que tu fais l'erreur colossale de croire que la norme était
écrite pour ne contenir que des choses « non bugguées ».
Certains aiment à dire que la charte du comité ANSI était de codifier
la partique existante, alors ... -- mais, en réalité c'est pas vrai,
le comité a fait mal d'inventions, y compris l'infame void* -> T*
et volatile.
"Charlie Gordon" writes:
[...]
| > En ce qui concerne le itoa() classique (issu de MS-DOS je pense), cet
| > équivalent simple n'existe pas, ou plutôt on en revient à sprintf() et un
| > calcul de la longueur de la chaîne en fonction des propriétés des types
| > entiers; et quand tu en es là, utiliser sprintf ou autre chose devient
| > anecdotique, sans parler de la lourdeur.
|
| Je ne crois pas que cet argument tienne : le fait qu'il existait déjà à
l'époque
| une alternative correcte à gets(), en l'occurrence fgets() est la raison qui
| aurait dû conduire à exclure gets() de la norme ANSI.
Je crois que tu fais l'erreur colossale de croire que la norme était
écrite pour ne contenir que des choses « non bugguées ».
Certains aiment à dire que la charte du comité ANSI était de codifier
la partique existante, alors ... -- mais, en réalité c'est pas vrai,
le comité a fait mal d'inventions, y compris l'infame void* -> T*
et volatile.
| C'est bien dommage qu'ils n'aient pas profité de l'occasion pour déprécier
| certaines saletés qui polluent encore la libc.
Du genre ?
| C'est bien dommage qu'ils n'aient pas profité de l'occasion pour déprécier
| certaines saletés qui polluent encore la libc.
Du genre ?
| C'est bien dommage qu'ils n'aient pas profité de l'occasion pour déprécier
| certaines saletés qui polluent encore la libc.
Du genre ?
"Antoine Leca" wrote in message
news:cm8h2i$u3q$avec une syntaxe
(snprintf) qui n'a rien a voir et qui n'est pas sans pièges.
Si tu passes tous les paramètres équivalents à ceux de strtol à
_ltostr, plus ceux pour gérer la chaîne et son allocation, tu va
finir avec une syntaxe plutôt lourde, tu ne crois pas ?
int ltostr(long n, char *buf, int size, int base);
qui retournerait si le resultat de la conversion tient dans le
buffer. est-ce si lourd ?
Je ne crois pas que cet argument tienne : le fait qu'il existait déjà
à l'époque une alternative correcte à gets(), en l'occurrence fgets()
est la raison qui aurait dû conduire à exclure gets() de la norme
ANSI.
contrairement à gets(), il est relativement simple d'éviter les
débordements avec itoa() en allouant un buffer destination
suffisamment grand (tant pis pour les architectures ou les entiers
font plus de 64 bits ;-)
ensuite il faut parser la syntaxe générale des formats de printf,
avec tous les flags et champs de controle
Puis on commence à formater avec en l'occurrence une
routine bien plus compliquée que itoa, puisqu'elle doit
potentiellement tenir compte de toutes les options sus-nommées.
Et enfin on recopie la chaine résultante en tenant compte des options
de cadrage et en verifiant l'overflow potentiel (snprintf)
Enfin, par expérience les programmes qui génèrent des chaînes de
caractères ne le font pas pour faire joli, ils finissent par ranger
ces chaînes quelque part, dans un fichier ou dans un socket, donc
ils finissent par être limités par le débit des entrées-sorties
C'est un a priori pas toujours justifié !
Avec des considérations comme cela, tu justifies tous les abus.
On peut aussi invoquer la loi de Moore : de toute façon, ça sert plus
à rien d'écrire du code efficace, les processeurs sont tellement
rapides !
A quoi bon faire des free() : aujourd'hui la mémoire est
si abondante et bon marché...
Pour finir, la vraie raison, c'est que itoa() n'existait pas sur les
bécanes Unix (plus précisement, sur V7).
En fait, c'est plus subtil que cela : la fonction itoa est un exemple
de boucle do/while dans le Kernighan et Ritchie de 1978, contemporain
de V7.
La version proposée est d'ailleurs beuguée pour le cas de INT_MIN :
Heureusement que i et j sont des int et non des size_t comme strlen()
PS: show me a do/while loop, I'll show you a bug.
"Antoine Leca" <root@localhost.gov> wrote in message
news:cm8h2i$u3q$1@shakotay.alphanet.ch...
avec une syntaxe
(snprintf) qui n'a rien a voir et qui n'est pas sans pièges.
Si tu passes tous les paramètres équivalents à ceux de strtol à
_ltostr, plus ceux pour gérer la chaîne et son allocation, tu va
finir avec une syntaxe plutôt lourde, tu ne crois pas ?
int ltostr(long n, char *buf, int size, int base);
qui retournerait si le resultat de la conversion tient dans le
buffer. est-ce si lourd ?
Je ne crois pas que cet argument tienne : le fait qu'il existait déjà
à l'époque une alternative correcte à gets(), en l'occurrence fgets()
est la raison qui aurait dû conduire à exclure gets() de la norme
ANSI.
contrairement à gets(), il est relativement simple d'éviter les
débordements avec itoa() en allouant un buffer destination
suffisamment grand (tant pis pour les architectures ou les entiers
font plus de 64 bits ;-)
ensuite il faut parser la syntaxe générale des formats de printf,
avec tous les flags et champs de controle
Puis on commence à formater avec en l'occurrence une
routine bien plus compliquée que itoa, puisqu'elle doit
potentiellement tenir compte de toutes les options sus-nommées.
Et enfin on recopie la chaine résultante en tenant compte des options
de cadrage et en verifiant l'overflow potentiel (snprintf)
Enfin, par expérience les programmes qui génèrent des chaînes de
caractères ne le font pas pour faire joli, ils finissent par ranger
ces chaînes quelque part, dans un fichier ou dans un socket, donc
ils finissent par être limités par le débit des entrées-sorties
C'est un a priori pas toujours justifié !
Avec des considérations comme cela, tu justifies tous les abus.
On peut aussi invoquer la loi de Moore : de toute façon, ça sert plus
à rien d'écrire du code efficace, les processeurs sont tellement
rapides !
A quoi bon faire des free() : aujourd'hui la mémoire est
si abondante et bon marché...
Pour finir, la vraie raison, c'est que itoa() n'existait pas sur les
bécanes Unix (plus précisement, sur V7).
En fait, c'est plus subtil que cela : la fonction itoa est un exemple
de boucle do/while dans le Kernighan et Ritchie de 1978, contemporain
de V7.
La version proposée est d'ailleurs beuguée pour le cas de INT_MIN :
Heureusement que i et j sont des int et non des size_t comme strlen()
PS: show me a do/while loop, I'll show you a bug.
"Antoine Leca" wrote in message
news:cm8h2i$u3q$avec une syntaxe
(snprintf) qui n'a rien a voir et qui n'est pas sans pièges.
Si tu passes tous les paramètres équivalents à ceux de strtol à
_ltostr, plus ceux pour gérer la chaîne et son allocation, tu va
finir avec une syntaxe plutôt lourde, tu ne crois pas ?
int ltostr(long n, char *buf, int size, int base);
qui retournerait si le resultat de la conversion tient dans le
buffer. est-ce si lourd ?
Je ne crois pas que cet argument tienne : le fait qu'il existait déjà
à l'époque une alternative correcte à gets(), en l'occurrence fgets()
est la raison qui aurait dû conduire à exclure gets() de la norme
ANSI.
contrairement à gets(), il est relativement simple d'éviter les
débordements avec itoa() en allouant un buffer destination
suffisamment grand (tant pis pour les architectures ou les entiers
font plus de 64 bits ;-)
ensuite il faut parser la syntaxe générale des formats de printf,
avec tous les flags et champs de controle
Puis on commence à formater avec en l'occurrence une
routine bien plus compliquée que itoa, puisqu'elle doit
potentiellement tenir compte de toutes les options sus-nommées.
Et enfin on recopie la chaine résultante en tenant compte des options
de cadrage et en verifiant l'overflow potentiel (snprintf)
Enfin, par expérience les programmes qui génèrent des chaînes de
caractères ne le font pas pour faire joli, ils finissent par ranger
ces chaînes quelque part, dans un fichier ou dans un socket, donc
ils finissent par être limités par le débit des entrées-sorties
C'est un a priori pas toujours justifié !
Avec des considérations comme cela, tu justifies tous les abus.
On peut aussi invoquer la loi de Moore : de toute façon, ça sert plus
à rien d'écrire du code efficace, les processeurs sont tellement
rapides !
A quoi bon faire des free() : aujourd'hui la mémoire est
si abondante et bon marché...
Pour finir, la vraie raison, c'est que itoa() n'existait pas sur les
bécanes Unix (plus précisement, sur V7).
En fait, c'est plus subtil que cela : la fonction itoa est un exemple
de boucle do/while dans le Kernighan et Ritchie de 1978, contemporain
de V7.
La version proposée est d'ailleurs beuguée pour le cas de INT_MIN :
Heureusement que i et j sont des int et non des size_t comme strlen()
PS: show me a do/while loop, I'll show you a bug.
En cmgg25$srs$, Charlie Gordon va escriure:int ltostr(long n, char *buf, int size, int base);
qui retournerait si le resultat de la conversion tient dans le
buffer. est-ce si lourd ?
Ta solution impose d'avoir alloué la chaîne avant l'appel. Donc, cela
revient exactement à snprintf, il n'y a pas réellement d'avantage si ce
n'est la possible rapidité (pas garantie) et le fait de traiter les bases
exotiques (et tu sais ce que j'en penses).
Si tu veux un équivalent de itoa() utilisable partout, il va falloir
rajouter un malloc() avant, et prévoir le free() quelque part; et là je dis
que cela devient lourd.
De plus, il manque quelques précisions:
Utilise-t-on des appels récursifs (plus rapide mais nécessite plus de pile)
ou deux passes (calcul de la longueur nécessaire puis génération des
chiffres en partant de la fin) ou un tampon intermédiaire "suffisament long"
(là encore, consome de la pile)?
Que se passe-t-il si cela ne tient pas? Rien, ou indéfini? Qu'est ce que
cela retourne? Comment recommencer?
Que se passe-t-il si n est piégé? Rien, ou indéfini? Veux-tu répéter le
problème de strtol() où il est impossible ou très difficile de savoir ce que
signifie LONG_MAX?
Quelle casse emploie-t-on? Quel jeu de chiffres quand plusieurs sont
possibles (arabe, écritures indiennes)?
Où met-on le signe? Et l'absence de signe?
Et pour finir, si tu choisis la solution simple dans tous ces cas-là, quel
est l'avantage par rapport à la version évidente programmée soi-même?
Je ne crois pas que cet argument tienne : le fait qu'il existait déjà
à l'époque une alternative correcte à gets(), en l'occurrence fgets()
est la raison qui aurait dû conduire à exclure gets() de la norme
ANSI.
Quand?
En 1986: c'était trop tôt, fgets n'était pas encore assez connu.
http://www.lysator.liu.se/c/rat/d9.html#4-9-7-2
En 1998: peut-être que oui. Je ne sais pas si cela a été discuté.
Voir aussi
http://groups.google.com/groups?hl=xx-hacker&selm`kjle%24u9%40dfw-ixnews10
.ix.netcom.com (Doug est dans le comité)
contrairement à gets(), il est relativement simple d'éviter les
débordements avec itoa() en allouant un buffer destination
suffisamment grand (tant pis pour les architectures ou les entiers
font plus de 64 bits ;-)
Comment fais-tu dans le cas général si tu ne veux pas ramener la
bibliothèque mathématique au passage? Tu alloue sizeof(int) * CHAR_BIT + 2 ?
ensuite il faut parser la syntaxe générale des formats de printf,
avec tous les flags et champs de controle
Euh? Le code est là, d'accord, mais il n'est pas utilisé: c'est un switch,
et par définition cette construction est plus efficace qu'une cascade de
if() else dans un cas comme celui-là.
Puis on commence à formater avec en l'occurrence une
routine bien plus compliquée que itoa, puisqu'elle doit
potentiellement tenir compte de toutes les options sus-nommées.
C'est bien là où se passe le problème.
Si cette routine n'est pas assez efficace sur ton implémentation, tu es en
présence d'un cas classique où l'optimisation d'une fonction de bibliothèque
est nécessaire. Sommes-nous d'accord que cela peut arriver pour bien d'autre
cas? Par exemple, il est des tonnes de programmes qui se suffisent de ctime
ou strftime, mais il m'est arrivé d'écrire un programme qui avait à traiter
de grandes quantités de formattage de dates, cela n'allait pas assez vite,
alors j'ai ré-écrit ma propre version dans mon cas particulier (qui testait
mes cas particuliers de fuseaux horaires et années bissextiles, pas les
autres). Idem pour mbrtowc: si tu en as besoin au c½ur de ton programme, la
version standard de la bibliothèque va plus que probablement pas être
satisfaisante...
La version proposée de itoa() dans K&R est d'ailleurs beuguée
pour le cas de INT_MIN :
Où est le bogue?
Parles-tu du bogue pédagogique (cf. l'exercice qui suit), destiné à attirer
l'attention sur les cas particuliers quand on écrit des fonctions « de
bibliothèque » à usage supposément non restreint?Heureusement que i et j sont des int et non des size_t comme strlen()
?
Avec size_t, tu n'as plus de bogue?
PS: show me a do/while loop, I'll show you a bug.
Quel est le rapport ?
Ou plus exactement, comme cet exemple est justement dans le paragraphe sur
do/while, que veux-tu démontrer là?
En cmgg25$srs$1@reader1.imaginet.fr, Charlie Gordon va escriure:
int ltostr(long n, char *buf, int size, int base);
qui retournerait si le resultat de la conversion tient dans le
buffer. est-ce si lourd ?
Ta solution impose d'avoir alloué la chaîne avant l'appel. Donc, cela
revient exactement à snprintf, il n'y a pas réellement d'avantage si ce
n'est la possible rapidité (pas garantie) et le fait de traiter les bases
exotiques (et tu sais ce que j'en penses).
Si tu veux un équivalent de itoa() utilisable partout, il va falloir
rajouter un malloc() avant, et prévoir le free() quelque part; et là je dis
que cela devient lourd.
De plus, il manque quelques précisions:
Utilise-t-on des appels récursifs (plus rapide mais nécessite plus de pile)
ou deux passes (calcul de la longueur nécessaire puis génération des
chiffres en partant de la fin) ou un tampon intermédiaire "suffisament long"
(là encore, consome de la pile)?
Que se passe-t-il si cela ne tient pas? Rien, ou indéfini? Qu'est ce que
cela retourne? Comment recommencer?
Que se passe-t-il si n est piégé? Rien, ou indéfini? Veux-tu répéter le
problème de strtol() où il est impossible ou très difficile de savoir ce que
signifie LONG_MAX?
Quelle casse emploie-t-on? Quel jeu de chiffres quand plusieurs sont
possibles (arabe, écritures indiennes)?
Où met-on le signe? Et l'absence de signe?
Et pour finir, si tu choisis la solution simple dans tous ces cas-là, quel
est l'avantage par rapport à la version évidente programmée soi-même?
Je ne crois pas que cet argument tienne : le fait qu'il existait déjà
à l'époque une alternative correcte à gets(), en l'occurrence fgets()
est la raison qui aurait dû conduire à exclure gets() de la norme
ANSI.
Quand?
En 1986: c'était trop tôt, fgets n'était pas encore assez connu.
http://www.lysator.liu.se/c/rat/d9.html#4-9-7-2
En 1998: peut-être que oui. Je ne sais pas si cela a été discuté.
Voir aussi
http://groups.google.com/groups?hl=xx-hacker&selm`kjle%24u9%40dfw-ixnews10
.ix.netcom.com (Doug est dans le comité)
contrairement à gets(), il est relativement simple d'éviter les
débordements avec itoa() en allouant un buffer destination
suffisamment grand (tant pis pour les architectures ou les entiers
font plus de 64 bits ;-)
Comment fais-tu dans le cas général si tu ne veux pas ramener la
bibliothèque mathématique au passage? Tu alloue sizeof(int) * CHAR_BIT + 2 ?
ensuite il faut parser la syntaxe générale des formats de printf,
avec tous les flags et champs de controle
Euh? Le code est là, d'accord, mais il n'est pas utilisé: c'est un switch,
et par définition cette construction est plus efficace qu'une cascade de
if() else dans un cas comme celui-là.
Puis on commence à formater avec en l'occurrence une
routine bien plus compliquée que itoa, puisqu'elle doit
potentiellement tenir compte de toutes les options sus-nommées.
C'est bien là où se passe le problème.
Si cette routine n'est pas assez efficace sur ton implémentation, tu es en
présence d'un cas classique où l'optimisation d'une fonction de bibliothèque
est nécessaire. Sommes-nous d'accord que cela peut arriver pour bien d'autre
cas? Par exemple, il est des tonnes de programmes qui se suffisent de ctime
ou strftime, mais il m'est arrivé d'écrire un programme qui avait à traiter
de grandes quantités de formattage de dates, cela n'allait pas assez vite,
alors j'ai ré-écrit ma propre version dans mon cas particulier (qui testait
mes cas particuliers de fuseaux horaires et années bissextiles, pas les
autres). Idem pour mbrtowc: si tu en as besoin au c½ur de ton programme, la
version standard de la bibliothèque va plus que probablement pas être
satisfaisante...
La version proposée de itoa() dans K&R est d'ailleurs beuguée
pour le cas de INT_MIN :
Où est le bogue?
Parles-tu du bogue pédagogique (cf. l'exercice qui suit), destiné à attirer
l'attention sur les cas particuliers quand on écrit des fonctions « de
bibliothèque » à usage supposément non restreint?
Heureusement que i et j sont des int et non des size_t comme strlen()
?
Avec size_t, tu n'as plus de bogue?
PS: show me a do/while loop, I'll show you a bug.
Quel est le rapport ?
Ou plus exactement, comme cet exemple est justement dans le paragraphe sur
do/while, que veux-tu démontrer là?
En cmgg25$srs$, Charlie Gordon va escriure:int ltostr(long n, char *buf, int size, int base);
qui retournerait si le resultat de la conversion tient dans le
buffer. est-ce si lourd ?
Ta solution impose d'avoir alloué la chaîne avant l'appel. Donc, cela
revient exactement à snprintf, il n'y a pas réellement d'avantage si ce
n'est la possible rapidité (pas garantie) et le fait de traiter les bases
exotiques (et tu sais ce que j'en penses).
Si tu veux un équivalent de itoa() utilisable partout, il va falloir
rajouter un malloc() avant, et prévoir le free() quelque part; et là je dis
que cela devient lourd.
De plus, il manque quelques précisions:
Utilise-t-on des appels récursifs (plus rapide mais nécessite plus de pile)
ou deux passes (calcul de la longueur nécessaire puis génération des
chiffres en partant de la fin) ou un tampon intermédiaire "suffisament long"
(là encore, consome de la pile)?
Que se passe-t-il si cela ne tient pas? Rien, ou indéfini? Qu'est ce que
cela retourne? Comment recommencer?
Que se passe-t-il si n est piégé? Rien, ou indéfini? Veux-tu répéter le
problème de strtol() où il est impossible ou très difficile de savoir ce que
signifie LONG_MAX?
Quelle casse emploie-t-on? Quel jeu de chiffres quand plusieurs sont
possibles (arabe, écritures indiennes)?
Où met-on le signe? Et l'absence de signe?
Et pour finir, si tu choisis la solution simple dans tous ces cas-là, quel
est l'avantage par rapport à la version évidente programmée soi-même?
Je ne crois pas que cet argument tienne : le fait qu'il existait déjà
à l'époque une alternative correcte à gets(), en l'occurrence fgets()
est la raison qui aurait dû conduire à exclure gets() de la norme
ANSI.
Quand?
En 1986: c'était trop tôt, fgets n'était pas encore assez connu.
http://www.lysator.liu.se/c/rat/d9.html#4-9-7-2
En 1998: peut-être que oui. Je ne sais pas si cela a été discuté.
Voir aussi
http://groups.google.com/groups?hl=xx-hacker&selm`kjle%24u9%40dfw-ixnews10
.ix.netcom.com (Doug est dans le comité)
contrairement à gets(), il est relativement simple d'éviter les
débordements avec itoa() en allouant un buffer destination
suffisamment grand (tant pis pour les architectures ou les entiers
font plus de 64 bits ;-)
Comment fais-tu dans le cas général si tu ne veux pas ramener la
bibliothèque mathématique au passage? Tu alloue sizeof(int) * CHAR_BIT + 2 ?
ensuite il faut parser la syntaxe générale des formats de printf,
avec tous les flags et champs de controle
Euh? Le code est là, d'accord, mais il n'est pas utilisé: c'est un switch,
et par définition cette construction est plus efficace qu'une cascade de
if() else dans un cas comme celui-là.
Puis on commence à formater avec en l'occurrence une
routine bien plus compliquée que itoa, puisqu'elle doit
potentiellement tenir compte de toutes les options sus-nommées.
C'est bien là où se passe le problème.
Si cette routine n'est pas assez efficace sur ton implémentation, tu es en
présence d'un cas classique où l'optimisation d'une fonction de bibliothèque
est nécessaire. Sommes-nous d'accord que cela peut arriver pour bien d'autre
cas? Par exemple, il est des tonnes de programmes qui se suffisent de ctime
ou strftime, mais il m'est arrivé d'écrire un programme qui avait à traiter
de grandes quantités de formattage de dates, cela n'allait pas assez vite,
alors j'ai ré-écrit ma propre version dans mon cas particulier (qui testait
mes cas particuliers de fuseaux horaires et années bissextiles, pas les
autres). Idem pour mbrtowc: si tu en as besoin au c½ur de ton programme, la
version standard de la bibliothèque va plus que probablement pas être
satisfaisante...
La version proposée de itoa() dans K&R est d'ailleurs beuguée
pour le cas de INT_MIN :
Où est le bogue?
Parles-tu du bogue pédagogique (cf. l'exercice qui suit), destiné à attirer
l'attention sur les cas particuliers quand on écrit des fonctions « de
bibliothèque » à usage supposément non restreint?Heureusement que i et j sont des int et non des size_t comme strlen()
?
Avec size_t, tu n'as plus de bogue?
PS: show me a do/while loop, I'll show you a bug.
Quel est le rapport ?
Ou plus exactement, comme cet exemple est justement dans le paragraphe sur
do/while, que veux-tu démontrer là?