Nutzen von strcpy und strcat



  • Wofür braucht man eigentlich strcpy oder strcat ?
    Wenn ich nicht sicher bin, dass der Zielbereich groß genug ist, ist das sehr gefährlich.
    Wenn ich weiß, dass der groß genug ist, kenne ich bereits alle Längen und kann memmove oder so benutzen.
    Also welchen Zweck haben diese Funktionen?





  • Die Funktionen sind für den Umgang mit Strings optimiert. Das sagt doch auch schon der Name.



  • Mir ist doch noch eine Verwendung für strcpy eingefallen.

    #include <string.h>
    #include <stdio.h>
    
    typedef struct Thing
    {
    	char name[1024];
    }
    Thing;
    
    void Thing_copy(Thing *to, Thing const *from)
    {
    	strcpy(to->name, from->name);
    }
    
    int main(void)
    {
    	Thing a = {""}, b = {""}, c = {"hallo"};
    
    	/*kopiert immer 1024 Zeichen*/
    	a = c;
    
    	puts(a.name);
    
    	/*kopiert nur so viel wie nötig*/
    	Thing_copy(&b, &c);
    
    	puts(b.name);
    	return 0;
    }
    

    Man kann damit in bestimmten Fällen unnötiges Kopieren von Zeichen vermeiden, wenn es unbedingt C-Strings sein sollen.



  • Ist strcpy nicht eh allermeistens so defininiert?

    void strcpy(char* dest, char const* src)
    {
        memcpy(dest, src, strlen(src));
    }
    

    Also einen großen Vorteil kann ich bei der Funktion wirklich nicht erkennen. Kann sogar eventuelles Optimierungspotential zerstören.



  • Es fehlt die Terminierung.
    Strcpy terminiert, memcpy terminiert nicht.



  • Stimmt. Also strlen() + 1. :p



  • ... 🙄
    Edit: Eigenen Stuss entfernt 😃



  • Ethon schrieb:

    Ist strcpy nicht eh allermeistens so defininiert?

    void strcpy(char* dest, char const* src)
    {
        memcpy(dest, src, strlen(src));
    }
    

    So ganz bestimmt nicht. Es gibt keinen Grund, zweimal durch den String zu laufen, um den Sentinel zu finden. Eine generische strcpy-Funktion kann etwa so aussehen:

    char *strcpy(char *dest, char const *src) {
      while((*dest++ = *src++))
        ;
    
      return dest;
    }
    

    In der Regel sind solche Funktionen aber in der C-Bibliothek für die entsprechende Architektur handoptimierter Assembly-Code. Lad dir mal den glibc-Code runter und kuck in sysdeps/x86_64/strcpy.S -- das ist ganz spannend. Die lesen da 8 Byte auf einmal, bestimmen (erst per Heuristik, ggf. nochmal gründlich), ob ein Null-Byte drin ist, und schieben den ganzen Block auf einmal in den Speicher, wenn das nicht der Fall ist. Da ist auch manuelles loop-unrolling drin. Das beinhaltet natürlich einige Annahmen über die Architektur und das Betriebssystem (insbesondere, dass eine Speicherseite nicht mitten im Mashchinenwort zuende geht).



  • Alle durch str* gekennzeichneten Funktionen der Standardbibliothek verlassen sich darauf, dass das relevante übergebene Argument auch die Stringkriterien erfüllt, nicht nur typbezogen (char[]) sondern insbesondere die Terminierung durch '\0', diese Funktionen haben also praktisch eine Längeninformation inklusive.
    mem* haben dies nicht und dafür einen obligatorischen zusätzlichen Parameter, der genau diese Längeninformation enthält.
    D.h. also auch, dass du Probleme bekommst, falls du an eine str* Funktion ein nicht-terminiertes char[] übergibst.


Anmelden zum Antworten