strlen eigenimplementierung?
-
size_t strlen(const char *s) { size_t l = 0; while (*s++) l++; return l; }Ginge natürlich mit haufenweise Tricks noch viel schneller, aber dann würde es nicht mehr in ein paar Zeilen passen.
-
Kleine Bemerkung: strlen hat kein def. Verhalten bei der Uebergabe eines NULL-Pointers. Meiner Erfahrung nach gibt es dann einen Crash - also immer sicher sein, dass der Parameter nicht NULL ist.
-
Ringding schrieb:
size_t strlen(const char *s) { size_t l = 0; while (*s++) l++; return l; }Ginge natürlich mit haufenweise Tricks noch viel schneller, aber dann würde es nicht mehr in ein paar Zeilen passen.
ich kenne mindestens einen compiler der hier tatsächlich zweimal pro durchgang inkrementiert. günstiger ist
size_t strlen(const char *s) { size_t l = 0; while (s[l++]); return l-1; }und wir haben sogar noch eine zeile gespart.
-
camper schrieb:
ich kenne mindestens einen compiler der hier tatsächlich zweimal pro durchgang inkrementiert.
Was? Das darf aber wirklich nicht sein. So weit glaube ich den Standard doch zu kennen, dass ich meinen Code mit Sicherheit als korrekt hinstellen kann. Würde mich interessieren, welcher Compiler das ist.
-
@Ringding: Korrekter Code hat noch lange nichts mit performantem Code zu tun.
MfG SideWinder
-
Was hat das mit Performanz zu tun? Ich habe ja extra geschrieben, dass man es viel schneller machen kann, aber dann wird's natürlich auch komplizierter.
-
oder so ungefähr:
int strlen (char *p)
{
char *q = p;
while (*p++)
;
return p-q;
}
-
Ist zwar genau so langsam wie die vorigen Varianten, aber im Unterschied dazu nicht einmal korrekt.
-
Ringding schrieb:
Ist zwar genau so langsam wie die vorigen Varianten, aber im Unterschied dazu nicht einmal korrekt.
nicht? zählt der eins zu weit oder zu wenig?
-
Eins zu weit.
-
Ringding schrieb:
Eins zu weit.
aber wenn
char *p = "";
dan gibt der doch 0 raus, oder?
-
Ich weiss, eigentlich kein C++, aber bei sowas juckt mir immer der Assembler-Finger:
size_t strlen( const char* str ) { _asm { push edi push ecx pushfd cld mov edi,str mov ecx,0XFFFFFFFF xor al,al repne scasb sub edi,str mov eax,edi popfd pop ecx pop edi } }
-
Darf ich auch mal:
size_t strlen(const char* s) { const char* p = s; while (*p != '\0') ++p; return p - s; }Ein Implementierung von strlen bringt aber nichts, weil viele Compiler sowas intrinsic drauf haben.
-
EDIT: hat sich erledigt
-
Power Off schrieb:
size_t strlen( const char* str ) { _asm { push edi push ecx pushfd cld mov edi,str mov ecx,0XFFFFFFFF xor al,al repne scasb sub edi,str mov eax,edi popfd pop ecx pop edi } }size_t optimized_strlen (const char* string) { __asm { mov eax,string test al,0x03 jnz compare main_loop: mov edx,[eax] add eax,0x04 mov ecx,edx sub edx,0x01010101 and edx,0x80808080 jz main_loop not ecx and edx,ecx jz main_loop test dl,dl jnz lret1 test dh,dh jnz lret2 test edx,0x00FF0000 jnz lret3 jmp lret4 compare: add eax,0x04 test byte ptr [eax-0x04],0xFF jz lret1 test byte ptr [eax-0x03],0xFF jz lret2 test byte ptr [eax-02h],0xFF jz lret3 dec eax and al,0xFC jmp main_loop lret1: dec eax lret2: dec eax lret3: dec eax lret4: mov ecx,string dec eax sub eax,ecx }; }SCNR

-
audacia schrieb:
size_t optimized_strlen (const char* string) { __asm { mov eax,string test al,0x03 jnz compare main_loop: mov edx,[eax] add eax,0x04 mov ecx,edx sub edx,0x01010101 and edx,0x80808080 jz main_loop not ecx and edx,ecx jz main_loop test dl,dl jnz lret1 test dh,dh jnz lret2 test edx,0x00FF0000 jnz lret3 jmp lret4 compare: add eax,0x04 test byte ptr [eax-0x04],0xFF jz lret1 test byte ptr [eax-0x03],0xFF jz lret2 test byte ptr [eax-02h],0xFF jz lret3 dec eax and al,0xFC jmp main_loop lret1: dec eax lret2: dec eax lret3: dec eax lret4: mov ecx,string dec eax sub eax,ecx }; }SCNR

Cool!!

Ist das schneller als "rep scasb"?
(wegen der Anzahl der Micro-Ops?)
-
Power Off schrieb:
Ist das schneller als "rep scasb"?
(wegen der Anzahl der Micro-Ops?)Sollte schneller sein, da die Daten nicht byteweise, sondern immer als Doublewords geladen und erst in den Registern näher untersucht werden.