J'ai un petit problème avec strcat/sprintf notamment en C.
En fait je "parse" un char* caractere par caractere, et je concatene ces
caracteres dans une autre chaine (chaineDest) de caractere char*.
Le probleme est que ma chaine chaineDest, si au depart je lui mets une
taille de 20, et que j'ai besoin ensuite de lui concatener plus de 20
caracteres, comment je fais ?
La solution que j'aurais tendance à utiliser est que quand je vois que
la taille devient trop courte, je sauvegarde ma chaine de caractere
(avec strcpy) chaineDest, je lui realloue la taille qu'il faut avec un
malloc, et je recopie ensuite dans l'autre sens pour remettre le contenu
de ma chaine sauvegardé dans la nouvelle chaine de taille plus grande.
Mais ca me parait abérant de faire ça pour toute concaténation en C ...
J'aime croire que le C n'est pas si barbare qu'on le dit, mais que c'est
plutot parce que je suis plus que juste en C ...
En dehors de quelques cas triviaux où memcpy est entièrement déroulé, memcpy doit s'exécuter dans une boucle où l'on teste que le bon nombre de caractère a été copié. C'est aussi long que de vérifier si le dernier caractère est atteint. memcpy peut être plus rapide que strcpy parce qu'il est plus facile de lui appliquer certaine optimisation tordue, comme la copie par bloc, mais c'est tout.
Sur x86, il y a possibilité d'insérer du code machine très rapide qui fait la copie en une ou deux instructions (sorte de DMA).
Si tu penses à REP MOVS, c'est généralement peu efficace sur les processeurs x86 actuels. Par exemple, pour le processeur que j'utilise actuellement (athlon-xp), on peut lire ici (p 68) : http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/22007.pdf
« The REP MOVS instructions are often not as efficient as an explicit loop which uses simple "RISC" instructions. » Les pages suivantes donnent plusieurs exemples de code assembleur pour réaliser un memcpy, le plus rapide étant 2 à 3 fois plus rapide que ceux basés sur de simple REP MOVS.
-- Richard
Richard Delorme wrote on 15/11/04 :
En dehors de quelques cas triviaux où memcpy est entièrement déroulé,
memcpy doit s'exécuter dans une boucle où l'on teste que le bon nombre
de caractère a été copié. C'est aussi long que de vérifier si le
dernier caractère est atteint. memcpy peut être plus rapide que strcpy
parce qu'il est plus facile de lui appliquer certaine optimisation
tordue, comme la copie par bloc, mais c'est tout.
Sur x86, il y a possibilité d'insérer du code machine très rapide qui
fait la copie en une ou deux instructions (sorte de DMA).
Si tu penses à REP MOVS, c'est généralement peu efficace sur les
processeurs x86 actuels. Par exemple, pour le processeur que j'utilise
actuellement (athlon-xp), on peut lire ici (p 68) :
http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/22007.pdf
« The REP MOVS instructions are often not as efficient as an explicit
loop which uses simple "RISC" instructions. »
Les pages suivantes donnent plusieurs exemples de code assembleur pour
réaliser un memcpy, le plus rapide étant 2 à 3 fois plus rapide que ceux
basés sur de simple REP MOVS.
En dehors de quelques cas triviaux où memcpy est entièrement déroulé, memcpy doit s'exécuter dans une boucle où l'on teste que le bon nombre de caractère a été copié. C'est aussi long que de vérifier si le dernier caractère est atteint. memcpy peut être plus rapide que strcpy parce qu'il est plus facile de lui appliquer certaine optimisation tordue, comme la copie par bloc, mais c'est tout.
Sur x86, il y a possibilité d'insérer du code machine très rapide qui fait la copie en une ou deux instructions (sorte de DMA).
Si tu penses à REP MOVS, c'est généralement peu efficace sur les processeurs x86 actuels. Par exemple, pour le processeur que j'utilise actuellement (athlon-xp), on peut lire ici (p 68) : http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/22007.pdf
« The REP MOVS instructions are often not as efficient as an explicit loop which uses simple "RISC" instructions. » Les pages suivantes donnent plusieurs exemples de code assembleur pour réaliser un memcpy, le plus rapide étant 2 à 3 fois plus rapide que ceux basés sur de simple REP MOVS.
-- Richard
Richard Delorme
"Richard Delorme" wrote in message news:41990722$0$15747$
La librairie standard glibc optimise memcpy a mort, remplaçant la plupart
des
appels par du code généré directement en lieu et place de l'appel, et particulierement efficace quant la taille de la copie est constante et l'alignement des pointeurs connu.
1) C'est le compilateur qui peut générer du code en ligne, pas une bibliothèque. 2) le memcpy de la glibc est plutôt lent.
Les headers font partie de la libc, ils contiennent des implementations en ligneet des macros qui font que le compilateur genere du code en ligne. C'est donc de la combinaison des deux que résult l'optimisation.
Oui et non. Indépendamment des entêtes et de la bibliothèque, gcc peut remplacer memcpy() par __builtin_memcpy() qui va générer un code enligne plus ou moins optimisé selon les circonstances.
Quelle expérience as-tu du memcpy de la glibc (utilisée dans des programmes compilés avec gcc) ? Quelle alternative connais-tu qui soit plus rapide ?
Par exemple xine, un programme de visualisation de vidéo sous X11 fait un petit test lors de sa première utilisation, où il compare le memcpy de la libc avec différents algorithmes :
L'algorithme qu'il utilise finalement est presque deux fois plus rapide que celui de la libc.
On peut sans doute faire encore mieux en lisant attentivement les conseils du fabriquant du micropresseur que l'on cible. Sur mon Athlon-XP, le plus rapide, pour des gros blocs de mémoire, est de faire un "prefetching" suivit d'une lecture par bloc avec les registres SSE.
-- Richard
"Richard Delorme" <abulmo@nospam.fr> wrote in message
news:41990722$0$15747$7a628cd7@news.club-internet.fr...
La librairie standard glibc optimise memcpy a mort, remplaçant la plupart
des
appels par du code généré directement en lieu et place de l'appel, et
particulierement efficace quant la taille de la copie est constante et
l'alignement des pointeurs connu.
1) C'est le compilateur qui peut générer du code en ligne, pas une
bibliothèque.
2) le memcpy de la glibc est plutôt lent.
Les headers font partie de la libc, ils contiennent des implementations en
ligneet des macros qui font que le compilateur genere du code en ligne. C'est
donc de la combinaison des deux que résult l'optimisation.
Oui et non. Indépendamment des entêtes et de la bibliothèque, gcc peut
remplacer memcpy() par __builtin_memcpy() qui va générer un code enligne
plus ou moins optimisé selon les circonstances.
Quelle expérience as-tu du memcpy de la glibc (utilisée dans des programmes
compilés avec gcc) ?
Quelle alternative connais-tu qui soit plus rapide ?
Par exemple xine, un programme de visualisation de vidéo sous X11 fait
un petit test lors de sa première utilisation, où il compare le memcpy
de la libc avec différents algorithmes :
L'algorithme qu'il utilise finalement est presque deux fois plus rapide
que celui de la libc.
On peut sans doute faire encore mieux en lisant attentivement les
conseils du fabriquant du micropresseur que l'on cible. Sur mon
Athlon-XP, le plus rapide, pour des gros blocs de mémoire, est de faire
un "prefetching" suivit d'une lecture par bloc avec les registres SSE.
"Richard Delorme" wrote in message news:41990722$0$15747$
La librairie standard glibc optimise memcpy a mort, remplaçant la plupart
des
appels par du code généré directement en lieu et place de l'appel, et particulierement efficace quant la taille de la copie est constante et l'alignement des pointeurs connu.
1) C'est le compilateur qui peut générer du code en ligne, pas une bibliothèque. 2) le memcpy de la glibc est plutôt lent.
Les headers font partie de la libc, ils contiennent des implementations en ligneet des macros qui font que le compilateur genere du code en ligne. C'est donc de la combinaison des deux que résult l'optimisation.
Oui et non. Indépendamment des entêtes et de la bibliothèque, gcc peut remplacer memcpy() par __builtin_memcpy() qui va générer un code enligne plus ou moins optimisé selon les circonstances.
Quelle expérience as-tu du memcpy de la glibc (utilisée dans des programmes compilés avec gcc) ? Quelle alternative connais-tu qui soit plus rapide ?
Par exemple xine, un programme de visualisation de vidéo sous X11 fait un petit test lors de sa première utilisation, où il compare le memcpy de la libc avec différents algorithmes :
L'algorithme qu'il utilise finalement est presque deux fois plus rapide que celui de la libc.
On peut sans doute faire encore mieux en lisant attentivement les conseils du fabriquant du micropresseur que l'on cible. Sur mon Athlon-XP, le plus rapide, pour des gros blocs de mémoire, est de faire un "prefetching" suivit d'une lecture par bloc avec les registres SSE.
-- Richard
cedric
Emmanuel Delahaye wrote:
Effectivement, mes connaissances en assembleur x86 sont anciennes et probablement dépassées.
Si ma mémoire est bonne c'était déjà déconseillé sur 486 (j'ai arreté l'assembleur intel à peut près à ce moment là)
Emmanuel Delahaye wrote:
Effectivement, mes connaissances en assembleur x86 sont anciennes et
probablement dépassées.
Si ma mémoire est bonne c'était déjà déconseillé sur 486 (j'ai arreté
l'assembleur intel à peut près à ce moment là)
Effectivement, mes connaissances en assembleur x86 sont anciennes et probablement dépassées.
Si ma mémoire est bonne c'était déjà déconseillé sur 486 (j'ai arreté l'assembleur intel à peut près à ce moment là)
Charlie Gordon
Quelle expérience as-tu du memcpy de la glibc (utilisée dans des programmes compilés avec gcc) ? Quelle alternative connais-tu qui soit plus rapide ?
Par exemple xine, un programme de visualisation de vidéo sous X11 fait un petit test lors de sa première utilisation, où il compare le memcpy de la libc avec différents algorithmes :
L'algorithme qu'il utilise finalement est presque deux fois plus rapide que celui de la libc.
On peut sans doute faire encore mieux en lisant attentivement les conseils du fabriquant du micropresseur que l'on cible. Sur mon Athlon-XP, le plus rapide, pour des gros blocs de mémoire, est de faire un "prefetching" suivit d'une lecture par bloc avec les registres SSE.
Oui, pour optimiser les transferts de gros blocs de memoire, on peut faire mieux que le code relativement générique de la glibc et utiliser des techniques lourdes, dont l'overhead et la spécificité sont importants, mais qui gagnent encore un facteur significatif pour des blocs appropriés (grande taille, contraintes particulières sur l'alignement et la taille, compatibilité avec l'utilisation des registres spéciaux...).
L'optimisation de memcpy par gcc/glibc marche quand même très bien pour le cas général, en particulier pour les petits blocs de taille connue à compile-time : copie de structures, copie de parties de tableaux, ou l'alignement est connu, la taille un multiple de la taille du mot et le code generé souvent ne fait meme pas de boucle. Le facteur gagné par de telles techniques sur l'appel d'une fonction de bibliothèque partagée est alors de bien supérieur à 2.
Chqrlie.
Quelle expérience as-tu du memcpy de la glibc (utilisée dans des programmes
compilés avec gcc) ?
Quelle alternative connais-tu qui soit plus rapide ?
Par exemple xine, un programme de visualisation de vidéo sous X11 fait
un petit test lors de sa première utilisation, où il compare le memcpy
de la libc avec différents algorithmes :
L'algorithme qu'il utilise finalement est presque deux fois plus rapide
que celui de la libc.
On peut sans doute faire encore mieux en lisant attentivement les
conseils du fabriquant du micropresseur que l'on cible. Sur mon
Athlon-XP, le plus rapide, pour des gros blocs de mémoire, est de faire
un "prefetching" suivit d'une lecture par bloc avec les registres SSE.
Oui, pour optimiser les transferts de gros blocs de memoire, on peut faire mieux
que le code relativement générique de la glibc et utiliser des techniques
lourdes, dont l'overhead et la spécificité sont importants, mais qui gagnent
encore un facteur significatif pour des blocs appropriés (grande taille,
contraintes particulières sur l'alignement et la taille, compatibilité avec
l'utilisation des registres spéciaux...).
L'optimisation de memcpy par gcc/glibc marche quand même très bien pour le cas
général, en particulier pour les petits blocs de taille connue à compile-time :
copie de structures, copie de parties de tableaux, ou l'alignement est connu, la
taille un multiple de la taille du mot et le code generé souvent ne fait meme
pas de boucle. Le facteur gagné par de telles techniques sur l'appel d'une
fonction de bibliothèque partagée est alors de bien supérieur à 2.
Quelle expérience as-tu du memcpy de la glibc (utilisée dans des programmes compilés avec gcc) ? Quelle alternative connais-tu qui soit plus rapide ?
Par exemple xine, un programme de visualisation de vidéo sous X11 fait un petit test lors de sa première utilisation, où il compare le memcpy de la libc avec différents algorithmes :
L'algorithme qu'il utilise finalement est presque deux fois plus rapide que celui de la libc.
On peut sans doute faire encore mieux en lisant attentivement les conseils du fabriquant du micropresseur que l'on cible. Sur mon Athlon-XP, le plus rapide, pour des gros blocs de mémoire, est de faire un "prefetching" suivit d'une lecture par bloc avec les registres SSE.
Oui, pour optimiser les transferts de gros blocs de memoire, on peut faire mieux que le code relativement générique de la glibc et utiliser des techniques lourdes, dont l'overhead et la spécificité sont importants, mais qui gagnent encore un facteur significatif pour des blocs appropriés (grande taille, contraintes particulières sur l'alignement et la taille, compatibilité avec l'utilisation des registres spéciaux...).
L'optimisation de memcpy par gcc/glibc marche quand même très bien pour le cas général, en particulier pour les petits blocs de taille connue à compile-time : copie de structures, copie de parties de tableaux, ou l'alignement est connu, la taille un multiple de la taille du mot et le code generé souvent ne fait meme pas de boucle. Le facteur gagné par de telles techniques sur l'appel d'une fonction de bibliothèque partagée est alors de bien supérieur à 2.
Chqrlie.
Marc Boyer
Charlie Gordon wrote:
"Targeur fou" wrote in message [SNIP]
Je ne partage pas ton optimisme, mais je connais qu'il m'a fallu beaucoup de temps pour admettre que la question n'est pas de maitriser ou non strncat ou strncpy, mais de refuser de piéger son propre code avec ces mines qui attendraient patiemment le programmeur suivant pour lui pourrir la vie avec leur sémantique ambiguë.
Comme je dois toujours: "Toujours prévoir que le code pourra être relu par quelqu'un de moins intelligent que soi." ;-)
Marc Boyer -- Je ne respecte plus le code de la route à vélo depuis une double fracture due au fait que j'étais le seul à le respecter.
Charlie Gordon wrote:
"Targeur fou" <rtroadec@yahoo.fr> wrote in message
[SNIP]
Je ne partage pas ton optimisme, mais je connais qu'il m'a fallu beaucoup de
temps pour admettre que la question n'est pas de maitriser ou non strncat ou
strncpy, mais de refuser de piéger son propre code avec ces mines qui
attendraient patiemment le programmeur suivant pour lui pourrir la vie avec leur
sémantique ambiguë.
Comme je dois toujours: "Toujours prévoir que le code pourra être
relu par quelqu'un de moins intelligent que soi." ;-)
Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.
Je ne partage pas ton optimisme, mais je connais qu'il m'a fallu beaucoup de temps pour admettre que la question n'est pas de maitriser ou non strncat ou strncpy, mais de refuser de piéger son propre code avec ces mines qui attendraient patiemment le programmeur suivant pour lui pourrir la vie avec leur sémantique ambiguë.
Comme je dois toujours: "Toujours prévoir que le code pourra être relu par quelqu'un de moins intelligent que soi." ;-)
Marc Boyer -- Je ne respecte plus le code de la route à vélo depuis une double fracture due au fait que j'étais le seul à le respecter.
Antoine Leca
En , Emmanuel Delahaye va escriure:
Sur x86, il y a possibilité d'insérer du code machine très rapide qui fait la copie en une ou deux instructions (sorte de DMA).
Depuis les Pentium (1993) ce n'est plus la méthode la plus efficace. Déjà avec les caches des 486 (1990), il y avait des manières de faire aussi vite avec des boucles explicites; et en déroulant les boucles tu gagnais.
D'autre part et pendant qu'on y est, à l'époque des 386/486, l'utilisation du DMA (mémoire-mémoire) permettait d'obtenir des performances plus qu'intéressantes sur des gros blocs, surtout sur des programmes multi-tâches: memcpy devient: tu programmes le DMA, tu attrapes le traitant d'interruption (ou mieux tu le branches sur awake()), tu lances le transfert et tu rends la main au scheduler. Au niveau des benchs, tu obtiens un memcpy indépendant de la longueur de bloc! Je ne sais pas comment marche les blitters d'aujourd'hui sur la mémoire principale (avec les caches L2/L3 cela doit être nettement moins clair).
Antoine
En mn.7cf27d4be6033250.15512@YOURBRAnoos.fr, Emmanuel Delahaye va escriure:
Sur x86, il y a possibilité d'insérer du code machine très rapide qui
fait la copie en une ou deux instructions (sorte de DMA).
Depuis les Pentium (1993) ce n'est plus la méthode la plus efficace.
Déjà avec les caches des 486 (1990), il y avait des manières de faire aussi
vite avec des boucles explicites; et en déroulant les boucles tu gagnais.
D'autre part et pendant qu'on y est, à l'époque des 386/486, l'utilisation
du DMA (mémoire-mémoire) permettait d'obtenir des performances plus
qu'intéressantes sur des gros blocs, surtout sur des programmes
multi-tâches: memcpy devient: tu programmes le DMA, tu attrapes le traitant
d'interruption (ou mieux tu le branches sur awake()), tu lances le transfert
et tu rends la main au scheduler. Au niveau des benchs, tu obtiens un memcpy
indépendant de la longueur de bloc!
Je ne sais pas comment marche les blitters d'aujourd'hui sur la mémoire
principale (avec les caches L2/L3 cela doit être nettement moins clair).
Sur x86, il y a possibilité d'insérer du code machine très rapide qui fait la copie en une ou deux instructions (sorte de DMA).
Depuis les Pentium (1993) ce n'est plus la méthode la plus efficace. Déjà avec les caches des 486 (1990), il y avait des manières de faire aussi vite avec des boucles explicites; et en déroulant les boucles tu gagnais.
D'autre part et pendant qu'on y est, à l'époque des 386/486, l'utilisation du DMA (mémoire-mémoire) permettait d'obtenir des performances plus qu'intéressantes sur des gros blocs, surtout sur des programmes multi-tâches: memcpy devient: tu programmes le DMA, tu attrapes le traitant d'interruption (ou mieux tu le branches sur awake()), tu lances le transfert et tu rends la main au scheduler. Au niveau des benchs, tu obtiens un memcpy indépendant de la longueur de bloc! Je ne sais pas comment marche les blitters d'aujourd'hui sur la mémoire principale (avec les caches L2/L3 cela doit être nettement moins clair).
Antoine
drkm
Marc Boyer writes:
Comme je dois toujours: "Toujours prévoir que le code pourra être relu par quelqu'un de moins intelligent que soi." ;-)
Moi de même, en me disant souvent que cet autre a de grandes chances d'être moi-même ...
--drkm
Marc Boyer <Marc.Boyer@enseeiht.yahoo.fr.invalid> writes:
Comme je dois toujours: "Toujours prévoir que le code pourra être
relu par quelqu'un de moins intelligent que soi." ;-)
Moi de même, en me disant souvent que cet autre a de grandes chances
d'être moi-même ...
Comme je dois toujours: "Toujours prévoir que le code pourra être relu par quelqu'un de moins intelligent que soi." ;-)
Moi de même, en me disant souvent que cet autre a de grandes chances d'être moi-même ...
--drkm
Pierre Maurette
drkm a écrit:
Marc Boyer writes:
Comme je dois toujours: "Toujours prévoir que le code pourra être relu par quelqu'un de moins intelligent que soi." ;-)
Moi de même, en me disant souvent que cet autre a de grandes chances d'être moi-même ... Moi, je n'ai pas ce problème, l'hypothèse de quelqu'un de moins
intelligent que moi étant improbable ;-) [oui, je sais, ce sera moi qui relirai le code] -- Pierre
drkm <usenet.fclcxx@fgeorges.org> a écrit:
Marc Boyer <Marc.Boyer@enseeiht.yahoo.fr.invalid> writes:
Comme je dois toujours: "Toujours prévoir que le code pourra être
relu par quelqu'un de moins intelligent que soi." ;-)
Moi de même, en me disant souvent que cet autre a de grandes chances
d'être moi-même ...
Moi, je n'ai pas ce problème, l'hypothèse de quelqu'un de moins
intelligent que moi étant improbable ;-)
[oui, je sais, ce sera moi qui relirai le code]
--
Pierre
Comme je dois toujours: "Toujours prévoir que le code pourra être relu par quelqu'un de moins intelligent que soi." ;-)
Moi de même, en me disant souvent que cet autre a de grandes chances d'être moi-même ... Moi, je n'ai pas ce problème, l'hypothèse de quelqu'un de moins
intelligent que moi étant improbable ;-) [oui, je sais, ce sera moi qui relirai le code] -- Pierre
rtroadec
"Charlie Gordon" wrote in message news:<cnarqd$n3k$...
"Targeur fou" wrote in message news:
"Charlie Gordon" wrote in message news:<cn6ho9$5m$...
size_t pos = strlen(s); if (pos < lng-1)
les unsigned ont encore frappé ! ce test se vautre si lng vaut 0 il faut mieux écrire pos + 1 < lng ou utiliser des ssize_t ou des int pour les tailles de tableau. qui plus est lng est mal choisi comme nom pour la taille du tableau, c'est trop
ambigu, on pourrait confondre avec la longueur de la chaine qui s'y trouve.
Aïe, bien vu, je me suis dit aujourd'hui "Tiens, je pourrais corriger par if (pos < (int)(lng-1))", et là, erreur fatale (cause priorité opérateurs), ça revient au même et c'est pire, ca obfusque davantage. if (pos < (int)lng-1) serait correct avec toutefois un avertissement sur la comparaison signé/non signé.
Hélas, non, cela ne suffirait pas, car la réalité est encore plus sordide :
La comparaison signé/non signé a une sémantique assez piégeuse que tu ne sembles pas encore maitriser. Le problème ici n'est pas la précédence des opérations, mais les règles d'arithmétique non-signée.
Hé hé, j'ai voulu faire le malin, mais j'avais complètement zappé les conversions engendrées par l'opérateur relationnel si bien expliquées par toi et Antoine.
[coupé]
Je ne partage pas ton optimisme, mais je connais qu'il m'a fallu beaucoup de temps pour admettre que la question n'est pas de maitriser ou non strncat ou strncpy, mais de refuser de piéger son propre code avec ces mines qui attendraient patiemment le programmeur suivant pour lui pourrir la vie avec leur sémantique ambiguë. La bonne solution est de ne pas utiliser ces saletés, voire d'en empêcher l'usage, et d'utiliser à la place des fonctions plus claires, implémentées localement.
Ca dépend, la preuve par l'exemple, le mien dans ce thread. Si le code que j'écris est susceptible de générer régulièrement des bugs vicieux à cause d'erreurs du même tenant que celle évoquée dans ce thread, je peux très bien me dire que je ne suis pas capable de créer des fonctions au moins aussi "correctes" que celles fournies avec une libc. C'est un travail que j'effectuerai quand j'aurai assez de temps pour l'effort de tests, mais en attendant, je préfère utiliser au maximum les fonctions de la libc, à peu près tout sauf gets().
Regis
"Charlie Gordon" <news@chqrlie.org> wrote in message news:<cnarqd$n3k$1@reader1.imaginet.fr>...
"Targeur fou" <rtroadec@yahoo.fr> wrote in message
news:99d640fa.0411150928.3364cd11@posting.google.com...
"Charlie Gordon" <news@chqrlie.org> wrote in message
news:<cn6ho9$5m$1@reader1.imaginet.fr>...
size_t pos = strlen(s);
if (pos < lng-1)
les unsigned ont encore frappé !
ce test se vautre si lng vaut 0
il faut mieux écrire pos + 1 < lng
ou utiliser des ssize_t ou des int pour les tailles de tableau.
qui plus est lng est mal choisi comme nom pour la taille du tableau, c'est
trop
ambigu, on pourrait confondre avec la longueur de la chaine qui s'y trouve.
Aïe, bien vu, je me suis dit aujourd'hui "Tiens, je pourrais corriger
par if (pos < (int)(lng-1))", et là, erreur fatale (cause priorité
opérateurs), ça revient au même et c'est pire, ca obfusque davantage.
if (pos < (int)lng-1) serait correct avec toutefois un avertissement
sur la comparaison signé/non signé.
Hélas, non, cela ne suffirait pas, car la réalité est encore plus sordide :
La comparaison signé/non signé a une sémantique assez piégeuse que tu ne sembles
pas encore maitriser.
Le problème ici n'est pas la précédence des opérations, mais les règles
d'arithmétique non-signée.
Hé hé, j'ai voulu faire le malin, mais j'avais complètement zappé les
conversions engendrées par l'opérateur relationnel si bien expliquées
par toi et Antoine.
[coupé]
Je ne partage pas ton optimisme, mais je connais qu'il m'a fallu beaucoup de
temps pour admettre que la question n'est pas de maitriser ou non strncat ou
strncpy, mais de refuser de piéger son propre code avec ces mines qui
attendraient patiemment le programmeur suivant pour lui pourrir la vie avec leur
sémantique ambiguë. La bonne solution est de ne pas utiliser ces saletés, voire
d'en empêcher l'usage, et d'utiliser à la place des fonctions plus claires,
implémentées localement.
Ca dépend, la preuve par l'exemple, le mien dans ce thread. Si le code
que j'écris est susceptible de générer régulièrement des bugs vicieux
à cause d'erreurs du même tenant que celle évoquée dans ce thread, je
peux très bien me dire que je ne suis pas capable de créer des
fonctions au moins aussi "correctes" que celles fournies avec une
libc. C'est un travail que j'effectuerai quand j'aurai assez de temps
pour l'effort de tests, mais en attendant, je préfère utiliser au
maximum les fonctions de la libc, à peu près tout sauf gets().
"Charlie Gordon" wrote in message news:<cnarqd$n3k$...
"Targeur fou" wrote in message news:
"Charlie Gordon" wrote in message news:<cn6ho9$5m$...
size_t pos = strlen(s); if (pos < lng-1)
les unsigned ont encore frappé ! ce test se vautre si lng vaut 0 il faut mieux écrire pos + 1 < lng ou utiliser des ssize_t ou des int pour les tailles de tableau. qui plus est lng est mal choisi comme nom pour la taille du tableau, c'est trop
ambigu, on pourrait confondre avec la longueur de la chaine qui s'y trouve.
Aïe, bien vu, je me suis dit aujourd'hui "Tiens, je pourrais corriger par if (pos < (int)(lng-1))", et là, erreur fatale (cause priorité opérateurs), ça revient au même et c'est pire, ca obfusque davantage. if (pos < (int)lng-1) serait correct avec toutefois un avertissement sur la comparaison signé/non signé.
Hélas, non, cela ne suffirait pas, car la réalité est encore plus sordide :
La comparaison signé/non signé a une sémantique assez piégeuse que tu ne sembles pas encore maitriser. Le problème ici n'est pas la précédence des opérations, mais les règles d'arithmétique non-signée.
Hé hé, j'ai voulu faire le malin, mais j'avais complètement zappé les conversions engendrées par l'opérateur relationnel si bien expliquées par toi et Antoine.
[coupé]
Je ne partage pas ton optimisme, mais je connais qu'il m'a fallu beaucoup de temps pour admettre que la question n'est pas de maitriser ou non strncat ou strncpy, mais de refuser de piéger son propre code avec ces mines qui attendraient patiemment le programmeur suivant pour lui pourrir la vie avec leur sémantique ambiguë. La bonne solution est de ne pas utiliser ces saletés, voire d'en empêcher l'usage, et d'utiliser à la place des fonctions plus claires, implémentées localement.
Ca dépend, la preuve par l'exemple, le mien dans ce thread. Si le code que j'écris est susceptible de générer régulièrement des bugs vicieux à cause d'erreurs du même tenant que celle évoquée dans ce thread, je peux très bien me dire que je ne suis pas capable de créer des fonctions au moins aussi "correctes" que celles fournies avec une libc. C'est un travail que j'effectuerai quand j'aurai assez de temps pour l'effort de tests, mais en attendant, je préfère utiliser au maximum les fonctions de la libc, à peu près tout sauf gets().