Heeft C een stringtype?

Ik ben onlangs begonnen met programmeren in C, afkomstig uit Java en Python. Nu heb ik in mijn boek opgemerkt dat om een “Hello World”-programma te maken, de syntaxis ongeveer als volgt is:

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

Dit voorbeeld gebruikt een char-array en ik vroeg me af: wat is er met strings gebeurd? Waarom kan ik er niet gewoon een gebruiken? Misschien is er een andere manier om dit te doen?


Antwoord 1, autoriteit 100%

C heeft en heeft nooit een native stringtype gehad. Volgens afspraak gebruikt de taal arrays van charafgesloten met een null char, d.w.z. met '\0'. Functies en macro’s in de standaardbibliotheken van de taal bieden ondersteuning voor de null-terminated character arrays, bijv. strlenherhaalt een array van chartotdat het een '\0'-teken en strcpykopieert van de broncode totdat het een '\0'tegenkomt.

Het gebruik van null-terminated strings in C weerspiegelt het feit dat C bedoeld was om slechts iets hoger te zijn dan assembler. Zero-terminated strings werden toen al direct ondersteund in assemblagetaal voor de PDP-10 en PDP-11.

Het is vermeldenswaard dat deze eigenschap van C-strings leidt tot nogal wat vervelende bufferoverloopbugs, waaronder ernstige beveiligingsfouten. Als u bijvoorbeeld vergeet een tekenreeks die als bronargument aan strcpyis doorgegeven, null te beëindigen, blijft de functie sequentiële bytes kopiëren van wat zich ook in het geheugen bevindt na het einde van de bronreeks totdat het komt toevallig een 0tegen, die mogelijk alle waardevolle informatie overschrijft die de locatie van de bestemmingsreeks in het geheugen volgt.

In uw codevoorbeeld is de letterlijke tekenreeks “Hallo, wereld!” wordt gecompileerd in een 14-byte lange array van char. De eerste 13 bytes bevatten de letters, komma’s, spatie en uitroepteken en de laatste byte bevat het null-terminator-teken '\0', dat automatisch voor u wordt toegevoegd door de compiler. Als u toegang zou krijgen tot het laatste element van de array, zou u vinden dat het gelijk is aan 0. Bijv.:

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

In uw voorbeeld is messageechter slechts 10 bytes lang. strcpygaat alle 14 bytes, inclusief de null-terminator, in het geheugen schrijven vanaf het adres van message. De eerste 10 bytes worden geschreven naar het geheugen dat op de stapel is toegewezen voor messageen de resterende vier bytes worden gewoon naar het einde van de stapel geschreven. Het gevolg van het schrijven van die vier extra bytes op de stapel is in dit geval moeilijk te voorspellen (in dit eenvoudige voorbeeld kan het geen kwaad), maar in echte code leidt dit meestal tot beschadigde gegevens of fouten bij de toegang tot het geheugen.


Antwoord 2, autoriteit 18%

Er is geen stringtype in C. Je moet char-arrays gebruiken.

Door de manier waarop uw code niet werkt, omdat de grootte van de array de hele array moet toestaan ​​om in te passen in plus één extra nul-beëindigend karakter.


Antwoord 3, Autoriteit 14%

Opmerking IT in de talen die u hebt genoemd:

Java:

String str = new String("Hello");

Python:

str = "Hello"

Zowel Java als Python hebben het concept van een “string”, C heeft het concept van een “string” niet. C heeft karakterarrays die kunnen komen in “alleen lezen” of manipuleerbaar.

C:

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

of

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'

Een karakterreeks is een reeks aaneengesloten tekens met een uniek schildvormig karakter aan het einde (normaal gesproken een null-terminator '\0'). Merk op dat het Sentinel-teken automatisch voor u is toegevoegd in de bovenstaande gevallen.


Antwoord 4, Autoriteit 10%

In C is een string eenvoudigweg een scala aan personages, eindigend met een nullbyte. Dus een char*is vaak uitgesproken “string”, wanneer u C-code leest.


Antwoord 5, Autoriteit 5%

C ondersteunt geen eersteklastype.

C++ heeft STD :: String


Antwoord 6

Ten eerste hoeft u dat niet allemaal te doen. In het bijzonder is de strcpyoverbodig – je hoeft geen string te kopiëren om hem gewoon te printf. Je messagekan worden gedefinieerd met die string op zijn plaats.

Ten tweede heb je niet genoeg ruimte gegeven voor die “Hallo wereld!” tekenreeks (messagemoet minimaal 14 tekens lang zijn, zodat de extra voor de null-terminator mogelijk is).

Over het waarom is het echter geschiedenis. In assembler zijn er geen strings, alleen bytes, woorden etc. Pascal had strings, maar daardoor waren er problemen met statisch typen – string[20]was een ander type dan string[40]. Zelfs in de begintijd waren er talen die dit probleem vermeden, maar dat veroorzaakte indirecte en dynamische toewijzingsoverheads, die destijds veel meer een efficiëntieprobleem waren.

C heeft er gewoon voor gekozen om de overheadkosten te vermijden en zeer laag te blijven. Strings zijn tekenreeksen. Arrays zijn zeer nauw verwant aan pointers die naar hun eerste item verwijzen. Wanneer arraytypes “vervallen” naar pointertypes, gaat de informatie over de buffergrootte verloren van het statische type, dus je krijgt niet de oude Pascal-tekenreeksproblemen.

In C++ is er de klasse std::stringdie veel van deze problemen vermijdt – en de dynamische toewijzingsoverheads heeft, maar tegenwoordig maken we ons daar meestal niet druk om. En in ieder geval is std::stringeen bibliotheekklasse – daaronder zit een C-stijl karakterarray-afhandeling.


Antwoord 7

C heeft geen eigen String-gegevenstype zoals Java.

Alleen wij kunnen het gegevenstype String in C declareren met een tekenarray of een tekenaanwijzer
Bijvoorbeeld:

char message[10]; 
 or 
 char *message;

Maar u moet minimaal aangeven:

   char message[14]; 

om “Hallo wereld!” te kopiëren in berichtvariabele.

  • 13 : lengte van de “Hallo wereld!”
  • 1 : voor ‘\0’ null-teken dat het einde van de tekenreeks identificeert

Other episodes