2013-02-05 9 views
24

Ich habe vor kurzem begonnen, in C zu programmieren, ausgehend von Java und Python. Nun, in meinem Buch habe ich bemerkt, dass ein „Hallo Welt“ Programm zu machen, ist die Syntax etwas wie folgt aus:Hat C einen String-Typ?

char message[10] 
strcpy(message, "Hello, world!") 
printf("%s\n", message); 

nun dieses Beispiel eine char-Array verwendet, und ich fragte mich - was in Strings passiert? Warum kann ich nicht einfach eins davon benutzen? Vielleicht gibt es einen anderen Weg, dies zu tun?

+7

C hat keine Zeichenfolgen. – sashoalm

+4

Sie brauchen char Nachricht [14]; – acraig5075

+3

Ihr strcpy wird übrigens Ihr Char-Array überlaufen. Sie benötigen mindestens ein Char-Array der Länge 14 (13 Zeichen + Nullterminator) – wich

Antwort

50

C hatte und hatte nie einen nativen String-Typ. Per Konvention verwendet die Sprache Arrays von char, die mit einem Null-Zeichen enden, d. H. Mit '\0'. Funktionen und Makros in den Standardbibliotheken der Sprache bieten Unterstützung für die nullterminierten Zeichenarrays, z. B. strlen, iteriert über ein Array von char, bis es auf '\0' Zeichen und strcpy Kopien von der Quellzeichenfolge trifft, bis es auf '\0' trifft.

Die Verwendung von Null-terminierten Strings in C spiegelt die Tatsache wider, dass C nur etwas mehr als die Assemblersprache sein sollte. Nullterminierte Strings wurden zu diesem Zeitpunkt bereits direkt in assembly language for the PDP-10 and PDP-11 unterstützt.

Es ist erwähnenswert, dass diese Eigenschaft von C-Strings zu einigen unangenehmen Buffer-Overrun-Fehlern führt, einschließlich schwerwiegender Sicherheitsmängel. Wenn Sie beispielsweise vergessen, eine Zeichenkette, die als Quellargument an strcpy übergeben wurde, auf Null zu setzen, kopiert die Funktion sequenzielle Bytes von dem, was sich im Speicher befindet, nach dem Ende der Quellzeichenfolge, bis sie zufällig auf 0 trifft. möglicherweise überschreibt jede wertvolle Information den Speicherort der Zielzeichenfolge im Speicher.

In Ihrem Codebeispiel wurde das Zeichenfolgenliteral "Hello, world!" wird in ein 14 Byte langes Array von char kompiliert. Die ersten 13 Bytes enthalten die Buchstaben, das Komma, das Leerzeichen und das Ausrufezeichen. Das letzte Byte enthält das Null-Beendigungszeichen '\0', das vom Compiler automatisch für Sie hinzugefügt wird. Wenn Sie auf das letzte Element des Arrays zugreifen würden, würden Sie es gleich 0 finden. Z.B .:

const char foo[] = "Hello, world!"; 
assert(foo[12] == '!'); 
assert(foo[13] == '\0'); 

jedoch in Ihrem Beispiel ist message nur 10 Byte lang. strcpy wird alle 14 Bytes, einschließlich des Null-Terminators, in den Speicher schreiben, beginnend mit der Adresse message. Die ersten 10 Bytes werden in den Speicher geschrieben, der auf dem Stack für message zugewiesen ist, und die verbleibenden vier Bytes werden einfach an das Ende des Stapels geschrieben. Die Konsequenz des Schreibens dieser vier zusätzlichen Bytes auf den Stapel ist in diesem Fall schwer vorherzusagen (in diesem einfachen Beispiel könnte es nichts schaden), aber in echtem Code führt dies normalerweise zu fehlerhaften Daten oder Speicherzugriffsverletzungsfehlern.

+1

Dies war die hilfreiche Antwort, Danke :) – arielschon12

3

C unterstützt keinen String-Typ der ersten Klasse.

C++ hat std :: string

11

Es gibt keine string Typ in C. Sie müssen Char-Arrays verwenden.

Übrigens wird Ihr Code nicht funktionieren, weil die Größe des Arrays für das gesamte Array und ein zusätzliches null abschließendes Zeichen passen sollte.

7

In C ist eine Zeichenfolge einfach ein Array von Zeichen, die mit einem Nullbyte enden. So wird eine char* oft als "String" ausgesprochen, wenn Sie C-Code lesen.

1

C hat keinen eigenen String-Datentyp wie Java.

Nur wir können String-Datentyp in C unter Verwendung von Zeichen-Array oder Zeichenzeiger Zum Beispiel erklären:

char message[10]; 
or 
char *message; 

Aber Sie müssen mindestens erklären:

char message[14]; 

„Hallo, Welt kopieren ! " in Nachrichtenvariable.

  • 13: Länge der "Hallo, Welt!"
  • 1: für ‚\ 0‘ Null-Zeichen, das Ende der Zeichenfolge
0

Erstens brauchen Sie nicht zu tun alles, was identifiziert. Insbesondere ist die strcpy redundant - Sie müssen keine Zeichenfolge nur auf printf kopieren. Ihre message kann mit dieser Zeichenfolge an Ort und Stelle definiert werden.

Zweitens haben Sie nicht genug Platz für das "Hallo, Welt!" string (message muss mindestens 14 Zeichen lang sein, wobei der zusätzliche für den Nullabschluss zulässig ist).

Auf dem warum, es ist Geschichte. In Assembler gibt es keine Strings, nur Bytes, Wörter usw. Pascal hatte Strings, aber da gab es Probleme mit der statischen Typisierung - string[20] war ein anderer Typ als string[40]. Es gab Sprachen schon in den Anfängen, die dieses Problem vermieden, aber das verursachte indirekte Kosten und dynamische Overhead-Kosten, die damals eher ein Effizienzproblem waren.

C einfach gewählt, um die Gemeinkosten zu vermeiden und sehr niedrigen Pegel zu bleiben. Zeichenfolgen sind Zeichenfelder. Arrays sind sehr eng mit Zeigern verwandt, die auf ihren ersten Eintrag zeigen. Wenn Array-Typen zu Zeigertypen "zerfallen", gehen die Puffergrößeninformationen vom statischen Typ verloren, so dass Sie die alten Pascal-String-Probleme nicht erhalten.

In C++ gibt es die std::string Klasse, die eine Menge dieser Probleme vermeidet - und hat die dynamischen Allokationsaufwand, aber heutzutage kümmern wir uns normalerweise nicht darum. Und in jedem Fall ist std::string eine Bibliotheksklasse - darunter gibt es C-Style-Character-Array-Handling.

4

es in den Sprachen beachten Sie erwähnt:

Java:

String str = new String("Hello"); 

Python:

str = "Hello" 

Sowohl Java und Python haben das Konzept eines "string", C tut nicht das Konzept einer "Zeichenfolge" haben. C hat Zeichenfelder, die "nur lesen" oder manipulierbar sein können.

C:

char * str = "Hello"; // the string "Hello\0" is pointed to by the character pointer 
         // str. This "string" can not be modified (read only) 

oder

char str[] = "Hello"; // the characters: 'H''e''l''l''o''\0' have been copied to the 
         // array str. You can change them via: str[x] = 't' 

ein Zeichenarray ist eine Sequenz von aufeinanderfolgenden Zeichen mit einem einzigartigen Sentinel-Zeichen am Ende (normalerweise ein NULL-Terminator '\0'). Beachten Sie, dass das Sentinel-Zeichen in den obigen Fällen automatisch an Sie angehängt wird.