2017-07-28 29 views
0

Ich bin in C-Sprache sehr neu. Ich habe versucht, strcat-Funktion zu verwenden.Wie funktioniert die Funktion strcat()?

#include <stdio.h> 
#include <string.h> 

int main(int argc, const char *argv[]) { 
    char s1[] = "12345"; 
    char s2[] = "abcde"; 

    strcat(s1, s2); 

    puts(s1); 
    puts(s2); 
    return 0; 
} 

Dieser normalerweise lief, aber

#include <stdio.h> 
#include <string.h> 

int main(int argc, const char *argv[]) { 
    char* s1 = "12345"; 
    char* s2 = "abcde"; 

    strcat(s1, s2); 

    puts(s1); 
    puts(s2); 
    return 0; 
} 

die letzte scheiterte ein Ergebnis zurück. Warum haben die zwei verschiedenen Arten der Deklaration unterschiedliche Ergebnisse in der strcat-Funktion zurückgegeben? Danke im Voraus. Sowohl der Code

+3

bash -> man strcat – Jonas

+2

Sie scheinen zu glauben, dass es den Speicher zuweist es braucht. Nun, das tut es nicht. – Siguza

+5

Beide sind undefiniertes Verhalten. – BLUEPIXY

Antwort

5

In C erstellt die Funktion strcat kein neues Zeichenarray mit verketteten Strings. Es hängt Zeichen aus der zweiten Zeichenfolge an die erste Zeichenfolge des ersten Zeichenarrays an, sofern es über genügend Elemente verfügt, um die neuen Zeichen zu speichern. Andernfalls versucht die Funktion, den Speicher über das Zeichenarray hinaus zu überschreiben, was zu undefiniertem Verhalten führt.

So eine gültige Verwendung der Funktion im ersten Programm kann auf folgende Weise aussehen

#include <stdio.h> 
#include <string.h> 

int main(int argc, const char *argv[]) { 
    char s1[11] = "12345"; 
    char s2[] = "abcde"; 

    strcat(s1, s2); 

    puts(s1); 
    puts(s2); 
    return 0; 
} 

In diesem Programm das Zeichenfeld als mit 11 Elementen deklariert wird. Somit ist es in der Lage, die angehängte Zeichenfolge "abcde" unterzubringen.

In dem zweiten Programm gibt es einen Versuch, die Stringliteral zu s1 durch den Zeiger gezeigt zu modifizieren. String-Literale in C und C++ sind unveränderbar. Jeder Versuch, ein Zeichenfolgenliteral zu ändern, führt zu undefiniertem Verhalten, obwohl in C entgegengesetzt zu C++ Zeichenfolgenliterale Arten von nichtkonstanten Zeichenfeldern aufweisen.

Von dem C Standard (6.4.5 Stringliterale)

7 Es ist nicht spezifiziert, ob diese Anordnungen verschieden wenn ihre Elemente haben die entsprechenden Werte sind. Wenn das Programm versucht, auf ein solches Array ändern, ist das Verhalten undefiniert.

Also im zweiten Programm müssen Sie wieder ein Zeichenarray mit genügend Elementen verwenden. Zum Beispiel

#include <stdio.h> 
#include <string.h> 

int main(int argc, const char *argv[]) { 
    char s1[11] = "12345"; 
    char* s2 = "abcde"; 

    strcat(s1, s2); 

    puts(s1); 
    puts(s2); 
    return 0; 
} 

Oder Sie entweder eine variable Länge Array (VLA), wenn der Compiler sie unterstützt oder dynamisch zuweisen ein Array verwenden könnte.Zum Beispiel

#include <stdio.h> 
#include <string.h> 

int main(int argc, const char *argv[]) { 
    char *s1 = "12345"; 
    char* s2 = "abcde"; 
    char s3[strlen(s1) + strlen(s2) + 1];  

    strcpy(s3, s1); 
    strcat(s3, s2); 

    puts(s1); 
    puts(s2); 
    puts(s3); 

    return 0; 
} 

Oder

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

int main(int argc, const char *argv[]) { 
    char *s1 = "12345"; 
    char* s2 = "abcde"; 
    char *s3 = malloc(strlen(s1) + strlen(s2) + 1);  

    if (s3 != NULL) 
    { 
     strcpy(s3, s1); 
     strcat(s3, s2); 

     puts(s1); 
     puts(s2); 
     puts(s3); 
    } 

    free(s3); 

    return 0; 
} 
+0

IMO, die alternative Sprache Diskussion (C++) beeinträchtigt, vor allem für ein "Ich bin sehr neu in C" OP, von dieser feinen C Antwort,. Schlagen Sie vor, die alternative Sprachdiskussion zu entfernen oder in einen späteren Teil der Antwort zu verschieben. – chux

+0

Vielen Dank für Ihre Antwort und Ihre Geduld aufrichtig. – zyx

+0

@zyx Überhaupt nicht. Bitte schön. –

7

Snippet nicht definiertes Verhalten aufzurufen. Im ersten Schnipsel s1 hat nicht genug Platz, um alle anderen Charakter als sechs Zeichen zu halten.
Im zweiten Schnipsel Sie versuchen, eine Stringliteral zu ändern. Jeder Versuch, ein Zeichenfolgenliteral zu ändern, führt zu undefiniertem Verhalten.

Lesen strcat man page:

[...] Die Saiten können sich überlappen nicht, und die dest Zeichenfolge muss für das Ergebnis genügend Platz haben. Wenn dest nicht groß genug ist, ist das Programmverhalten nicht vorhersehbar; Pufferüberläufe sind ein beliebter Weg, um sichere Programme zu attackieren.

+0

Alle folgenden sind "besser": Linux: http://man7.org/linux/man-pages/man3/strcat.3.html, Linux/POSIX: http://man7.org/linux/man-pages /man3/strcat.3p.html, POSIX: http://pubs.opengroup.org/onlinepubs/9699919799/functions/strcat.html, C11-Standard: http://port70.net/~nsz/c/c11/ n1570.html # 7.24.3.1 dann dieses "* linux.die.net *" -Spam-Zeug ... oder? – alk

+2

@alk; Änderte es. BTW, warum ist es Spam? – haccks

+0

Filtert Ihr Browser alle Werbung aus, die diese Seiten an meinen Schreibtisch tragen? – alk

Verwandte Themen