julien_boss
Messages postés165Date d'inscriptionsamedi 4 juin 2005StatutMembreDernière intervention24 octobre 2007
-
7 juin 2007 à 12:51
ranzi
Messages postés2Date d'inscriptionlundi 7 mai 2007StatutMembreDernière intervention17 août 2010
-
17 août 2010 à 15:58
Bonjour,
j'ai codé cette fonction, sensée être l'équivalent de string::substr(...) en C :
char * StrSub(const char *s, int pos, int len)
{
char *ps = (char*)s;
static char rs[256];
char *prs = rs;
int strLen = strlen(s);
qui affichera deux fois "une p", au lieu de "une p" puis "hrase" .
Je ne comprends pas l'erreur, et comme je ne maitrise pas tout à fait les pointeurs, je demande à un oeil avisé de bien vouloir me dire où ca coince. Merci bcp
julien_boss
Messages postés165Date d'inscriptionsamedi 4 juin 2005StatutMembreDernière intervention24 octobre 2007 7 juin 2007 à 15:08
Merci pour vos codes, ca m'a permis de voir mon erreur. Mais il n'y a pas un moyen de retourner directement une chaine statique, bien que j'ai du mal à en voir un ? :s
apres, disons que je programme dans quelques langages d'une facon similaire (quand je le peux evidement), peut-etre pour pouvoir relire tout ce que je fais meme apres une pause de quelques mois sur un langage... Ainsi, je n'utilise pas goto, pas switch, ... je sais que ca ne fait pas souvent un code parfait, je demandais juste si pour goto, ca faisait gagner du temps d'execution, pour malgre les imprefections de mon travail, savoir ce que j'ai a gagner a le perfectionner... (ne pas dupliquer du code, c'est un bon argument, mais tu tapes un label, deux goto, je tapes un break; et deux lignes, donc malgre le fait d'avoir duplique du code, j'en ai ecrit autant)
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 7 juin 2007 à 15:15
Peu importe les lignes de C, ce qui est à comparer est l'asm généré par le compilo, je verrai en soirée.
Je ne pense pas qu'un simple label aussi causant que 'subEXIT' gênera la compréhension de la fonction même 10 ans plus tard.
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 7 juin 2007 à 15:18
julien_boss > prends par habitude de ne jamais retourner une chaine ou autre tableau statique. L'appelant doit être responsable des params passés, ça garantit l'usage à long terme de la fonction.
Ex: longueur de ton buffer statique ira toujours ??? ben non.
coucou747
Messages postés12303Date d'inscriptionmardi 10 février 2004StatutMembreDernière intervention30 juillet 201244 7 juin 2007 à 19:37
je ne suis pas aussi categorique... c'etait une question, pas une critique...
en php, ils ajoutent l'objet a la v5 et le goto a la v6... c'est un langage que je connais bien, mais ils font n'imp de ce cote... surtout en php, on est souvent limite a des choes simples, alors faire sans goto... c'est pas trop complique...
asm, j'en ai jamais fait, mais j'ai entendu parler de jump qui ressembleraient aux gotos...
tu prends un langage vraiment moche : le tibasic, t'as pas de procedures, si on veut decouper, faut inclure des "fichiers" mais pour passer des variables, c'est pas top...
tant qu'on a pas appuye sur une touche
:lbl 1
:getkey->k
:if k=0
:then
:goto 1
:end
tu vas beaucou rire :) (error memory au bout de 30 secondes, et un programme super lent si jamais t'appuis sur une touche entre temps... ca te bourre la pile d'une attente de ":end")
Bref, en C, c'est probablement parfaitement compile, mais en php, laisse moi rire...
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 7 juin 2007 à 20:07
Mon message est à prendre au deuxième degré.
Et vivi en asm y a jmp qui est tout à fait un goto sans compter les
je/jne et variantes qui servent de saut conditionnel. Mais il ne
s'écrit pas goto !
Sur le coup du tibasic, ça été mon deuxième langage après celui de ma
casio ! Ca me surprend le coup de l'erreur. M'enfin ça fait un bail que
j'ai pas touché une TI...
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 7 juin 2007 à 20:09
'JMP addr' asm correspond stricto senso au 'goto label' du C.
Un binaire est rempli d'instructions de saut.
if, do, while, etc... absolument partout le compilo génère des sauts. Les goto y seront qu'on les masque ou non, aucun autre moyen de faire un code réagissant à des conditions.
Même un appel de fonction est un saut après empilage de EIP et ensuite des params, retour de la fonction idem un saut.
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 11 juin 2007 à 08:51
Bon, comme BruNews a pas l'air de se décider, voyons ce que ça donne côté compilation.
Config :
VC2005 pro (MSDN AA).
Release.
Optimisation complète.
Privilégie le code rapide.
Jeu de caractère multi octet.
Compiler comme code C.
Convention en stdcall.
J'ai remplacé le :
if(!len) goto subEXIT;
malencontreusement oublié dans les modifs de coucou747 par un :
if(!len) return 0;
Une question : pourquoi s est const ?
Cela ne devrait pas nous empècher de le modifier ?
Les deux routines ont été inlinées par le compilo.
Le tampon de réception est en esp+18.
eax pointera la chaîne source, ecx la chaîne de destination.
Le test sur la longueur à été supprimé puisque inutile dans ce cas particulier.
De même le test sur pos.
La valeur de retour n'est pas calculée puisque non utilisé.
Les add et les sub auraient dûes être logiquement des inc et des dec, plus compactes.
StrSubWithGoto :
mov edi, 5
mov esi, 2
mov eax, s
lea ecx, dword ptr [esp+18]
loop1:
if(*s++ == 0) goto subEXIT;
mov dl, byte ptr [eax]
add eax, 1
test dl, dl
je subEXIT
while(--pos);
sub esi, 1
jne loop1
loop2:
if((*p *s) 0) goto subEXIT;
mov dl, byte ptr [eax]
test dl, dl
mov byte ptr [ecx], dl
je subEXIT
p++; s++;
add ecx, 1
add eax, 1
while(--len);
sub edi, 1
jne loop2
subEXIT:
(..)
*p = 0;
mov byte ptr [ecx], 00
StrSubWithoutGoto :
Faudrat que l'on m'explique l'intérêt du lea ecx, dword ptr[ecx+00]...
Le mov edi, edi est lui aussi manifique...
mov edi, 5
mov esi, 2
mov eax, s
lea ecx, dword ptr[esp+18]
lea ecx, dword ptr[ecx+00]
loop1:
if(*s++ 0) { *p 0; return (p - szdst); }
mov dl, byte ptr[eax]
add eax, 1
test dl, dl
je trèsLoin
while(--pos);
sub esi, 1
jne loop1
mov edi, edi
loop2:
if((*p *s) 0) break;
mov dl, byte ptr [eax]
test dl, dl
mov byte ptr [ecx], dl
je subEXIT
p++; s++;
add ecx, 1
add eax, 1
while(--len);
sub edi, 1
jne loop2
subEXIT:
*p = 0;
mov byte ptr [ecx], 0
(..)
trèsLoin:
Comparatif :
Si on exclut les 2 instructions (très) bizarres, le code est quasi identique.
Le goto s'en sort donc un peu mieux dans ce cas précis, mais plutôt à cause du compilo qu'autre chose.
Mon compilo préféré s'est par exemple abstenu de générer ces deux lignes...
Je me demande si le seul vrai critère d'emploi ou pas du goto ne serait pas :
Mon chef aime-t-il les goto ?
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 11 juin 2007 à 10:01
Là où le compilo a un énorme avantage c'est sur l'alignement des instructions comme des données, c'est fait à tout coup.
'inc' et 'dec' étant plus compact, il fallait souvent injecter des octets de cadrage pour alignement.
On ajoutera que ces instructions ne sont plus encodables en x64 sur R16 et R32, elles ont été enlevées pour leur équivalent 'add' et 'sub' ainsi plus de problème.