C strenghåndtering - C string handling

Den C programmeringssprog har en række funktioner til gennemførelse af operationer på strings (tegnstrenge og byte strenge) i sin standard bibliotek . Forskellige operationer, såsom kopiering, sammenkædning , tokenisering og søgning understøttes. For tegnstrenge bruger standardbiblioteket konventionen om, at strenge er nul-afsluttede : en streng med n tegn er repræsenteret som en matrix med n + 1 elementer, hvoraf det sidste er et NULtegn (med numerisk værdi 0).

Den eneste understøttelse af strenge i det korrekte programmeringssprog er, at kompilatoren oversætter citerede strengkonstanter til null-terminerede strenge.

Definitioner

En streng defineres som en sammenhængende sekvens af kodenheder, der afsluttes af den første nulkodenhed (ofte kaldet NUL -kodenheden ). Det betyder, at en streng ikke kan indeholde nulkodenheden, da den første, der ses, markerer slutningen af ​​strengen. Den længde af en streng er antallet af kode enheder før den nul kode enhed. Hukommelsen optaget af en streng er altid en kodeenhed mere end længden, da der er brug for plads til at gemme nulterminatoren.

Generelt betyder udtrykket streng en streng, hvor kodenheden er af typen char, som er nøjagtigt 8 bit på alle moderne maskiner. C90 definerer brede strenge, der bruger en kodeenhed af typen wchar_t, som er 16 eller 32 bit på moderne maskiner. Dette var beregnet til Unicode, men det er stadig mere almindeligt at bruge UTF-8 i normale strenge til Unicode i stedet.

Strenge overføres til funktioner ved at sende en markør til den første kodeenhed. Da char*og wchar_t*er forskellige typer, er de funktioner, der behandler brede strenge, forskellige fra dem, der behandler normale strenge og har forskellige navne.

Strenge ( "text"i C -kildekoden) konverteres til arrays under kompilering. Resultatet er en række kodenheder, der indeholder alle tegnene plus en efterfølgende nulkodenhed. I C90 L"text"producerer en bred streng. En streng bogstavelig kan indeholde nulkodenheden (en måde er at sætte \0i kilden), men dette får strengen til at ende på det tidspunkt. Resten af ​​det bogstavelige vil blive placeret i hukommelsen (med en anden nulkodenhed tilføjet til slutningen), men det er umuligt at vide, at disse kodenheder blev oversat fra strengen bogstavelig, derfor er en sådan kildekode ikke en strenglitteral.

Tegnkoder

Hver streng slutter ved den første forekomst af nulkodenheden af ​​den relevante slags ( chareller wchar_t). Derfor kan en byte-streng ( char*) indeholde ikke- NUL- tegn i ASCII eller en hvilken som helst ASCII-udvidelse , men ikke tegn i kodninger som UTF-16 (selvom en 16-bit kodeenhed kan være uden nul, kan dens høje eller lave byte være nul). Kodningerne, der kan lagres i brede strenge, er defineret af bredden på wchar_t. I de fleste implementeringer wchar_ter mindst 16 bit, og derfor kan alle 16-bit kodninger, såsom UCS-2 , gemmes. Hvis wchar_ter 32-bit, kan 32-bit kodninger, såsom UTF-32 , gemmes. (Standarden kræver en "type, der har et hvilket som helst bredt tegn", som i Windows ikke længere er sandt siden UCS-2 til UTF-16-skiftet.) C ++ 11 og C11 tilføjer to typer med eksplicitte bredder char16_tog char32_t.

Koder med variabel bredde kan bruges i både byte-strenge og brede strenge. Strenglængde og forskydninger måles i bytes eller wchar_tikke i "tegn", hvilket kan være forvirrende for begyndende programmører. UTF-8 og Shift JIS bruges ofte i C-byte-strenge, mens UTF-16 ofte bruges i C-brede strenge, når der wchar_ter 16 bits. Afkortning af strenge med tegn med variabel længde ved hjælp af funktioner som f.eks. strncpyKan producere ugyldige sekvenser i slutningen af ​​strengen. Dette kan være usikkert, hvis de afkortede dele fortolkes med kode, der antager, at input er gyldigt.

Understøttelse af Unicode-bogstaver som char foo[512] = "φωωβαρ";(UTF-8) eller wchar_t foo[512] = L"φωωβαρ";(UTF-16 eller UTF-32 afhænger af wchar_t) er implementeringsdefineret og kan kræve, at kildekoden er i den samme kodning, især for charhvor kompilatorer bare kan kopiere, hvad der er mellem citaterne. Nogle kompilatorer eller redaktører kræver, at alle ikke-ASCII-tegn indtastes som \xNNsekvenser for hver byte af UTF-8 og/eller \uNNNNfor hvert ord i UTF-16. Siden C11 (og C ++ 11) er en ny char foo[512] = u8"φωωβαρ";bogstavelig syntaks tilgængelig, der garanterer UTF-8 for en bytring-bogstavelig.

Oversigt over funktioner

De fleste af de funktioner, der fungerer på C -strenge, er deklareret i string.hoverskriften ( cstringi C ++), mens funktioner, der fungerer på C -brede strenge, er deklareret i wchar.hoverskriften ( cwchari C ++). Disse overskrifter indeholder også deklarationer over funktioner, der bruges til håndtering af hukommelsesbuffere; navnet er således noget af en forkert betegnelse.

Funktioner, der er angivet i, string.her ekstremt populære, da de som en del af C -standardbiblioteket garanteret fungerer på enhver platform, der understøtter C.Men der findes nogle sikkerhedsproblemer med disse funktioner, f.eks. Potentielle bufferoverløb, når de ikke bruges omhyggeligt og korrekt , hvilket får programmørerne til at foretrække sikrere og muligvis mindre bærbare varianter, hvoraf nogle populære er angivet nedenfor. Nogle af disse funktioner krænker også const-korrekthed ved at acceptere en conststrengmarkør og returnere en ikke- constpeger i strengen. For at rette op på dette er nogle blevet adskilt i to overbelastede funktioner i C ++ - versionen af ​​standardbiblioteket.

I historisk dokumentation blev udtrykket "karakter" ofte brugt i stedet for "byte" for C-strenge, hvilket får mange til at tro, at disse funktioner på en eller anden måde ikke fungerer for UTF-8 . Faktisk er alle længder defineret som værende i bytes, og dette er sandt i alle implementeringer, og disse funktioner fungerer lige så godt med UTF-8 som med enkeltbyte-kodninger. BSD -dokumentationen er blevet rettet for at gøre dette klart, men POSIX-, Linux- og Windows -dokumentation bruger stadig "tegn" mange steder, hvor "byte" eller "wchar_t" er det korrekte udtryk.

Funktioner til håndtering af hukommelsesbuffere kan behandle sekvenser af bytes, der indeholder null-byte som en del af dataene. Navne på disse funktioner starter typisk med mem, som modsat strpræfikset.

Konstanter og typer

Navn Noter
NULL Makro udvides til nulmarkørkonstanten ; det vil sige en konstant, der repræsenterer en markørværdi, som garanteret ikke er en gyldig adresse for et objekt i hukommelsen.
wchar_t Type, der bruges til en kodeenhed i brede strenge, normalt en usigneret 16 bit eller 32 bit værdi. Der er ikke angivet nogen specifik fortolkning for disse kodeenheder; C standard kræver blot, at wchar_t være brede nok til at holde det bredeste tegnsæt blandt de understøttede systemets locales . Teoretisk set kan wchar_t have samme størrelse som char og dermed ikke være i stand til at holde UTF-32 eller UTF-16 kodeenheder.
wint_t Heltalstype, der kan indeholde enhver værdi af en wchar_t samt værdien af ​​makroen WEOF. Denne type er uændret ved integrerede kampagner. Normalt en 32 bit signeret værdi.
mbstate_t Indeholder alle oplysninger om den konverteringstilstand, der kræves fra det ene opkald til en funktion til det andet.

Funktioner

Byte
streng
Bred
snor
Beskrivelse
String
manipulation
strcpy wcscpy Kopierer en streng til en anden
strncpy wcsncpy Skriver nøjagtigt n bytes, kopierer fra kilde eller tilføjer nuller
strcat wcscat Tilføjer en streng til en anden
strncat wcsncat Tilføjer ikke mere end n bytes fra en streng til en anden
strxfrm wcsxfrm Transformerer en streng i henhold til den aktuelle lokalitet
String
undersøgelse
strlen wcslen Returnerer længden af ​​strengen
strcmp wcscmp Sammenligner to strenge ( trevejs sammenligning )
strncmp wcsncmp Sammenligner et bestemt antal bytes i to strenge
strcoll wcscoll Sammenligner to strenge i henhold til den aktuelle lokalitet
strchr wcschr Finder den første forekomst af en byte i en streng
strrchr wcsrchr Finder den sidste forekomst af en byte i en streng
strspn wcsspn Returnerer antallet af indledende bytes i en streng, der er i en anden streng
strcspn wcscspn Returnerer antallet af indledende bytes i en streng, der ikke er i en anden streng
strpbrk wcspbrk Finder i en streng den første forekomst af en byte i et sæt
strstr wcsstr Finder den første forekomst af en delstreng i en streng
strtok wcstok Opdeler en streng i tokens
Diverse strerror Ikke relevant Returnerer en streng, der indeholder en meddelelse, der stammer fra en fejlkode
Hukommelse
manipulation
memset wmemset Fylder en buffer med en gentaget byte
memcpy wmemcpy Kopierer en buffer til en anden
memmove wmemmove Kopierer en buffer til en anden, muligvis overlappende buffer
memcmp wmemcmp Sammenligner to buffere (trevejs sammenligning)
memchr wmemchr Finder den første forekomst af en byte i en buffer
  1. ^ For brede strengfunktioner erstatteswchar_t"byte" i beskrivelsen

Multibyte funktioner

Navn Beskrivelse
mblen Returnerer antallet af bytes i det næste multibyte -tegn
mbtowc Konverterer det næste multibyttegn til et bredt tegn
wctomb Konverterer en bred karakter til dens multibyte -repræsentation
mbstowcs Konverterer en multibyte streng til en bred streng
wcstombs Konverterer en bred streng til en multibyte streng
btowc Konverter et enkelt-byte tegn til et bredt tegn, hvis det er muligt
wctob Konverter et bredt tegn til et enkelt-byte tegn, hvis det er muligt
mbsinit Kontrollerer, om et tilstandsobjekt repræsenterer initialtilstand
mbrlen Returnerer antallet af bytes i det næste multibyte -tegn, givet tilstand
mbrtowc Konverterer det næste multibyttegn til et bredt tegn, givet tilstand
wcrtomb Konverterer en bred karakter til dens multibyte -repræsentation, givet tilstand
mbsrtowcs Konverterer en multibyte streng til en bred streng, givet tilstand
wcsrtombs Konverterer en bred streng til en multibyte streng, givet tilstand

Disse funktioner tager alle en markør til a mbstate_tobjekt, som den, der ringer op, skal vedligeholde. Dette var oprindeligt beregnet til at spore skiftestater imbkodninger, men moderne dem som UTF-8 har ikke brug for dette. Disse funktioner blev dog designet med den antagelse, atToiletkodning er ikke en kodning med variabel bredde og er derfor designet til at håndtere præcis enwchar_tad gangen, videregive den efter værdi frem for at bruge en strengmarkør. Da UTF-16 er en kodning med variabel bredde, ermbstate_t er blevet genbrugt til at holde styr på surrogatpar i den brede kodning, selvom opkalderen stadig skal registrere og ringe mbtowc to gange for en enkelt karakter.

Numeriske konverteringer

Byte
streng
Bred
snor
Beskrivelse
atof Ikke relevant konverterer en streng til en floating-point værdi ('atof' betyder 'ASCII til float')
atoi
atol
atoll
Ikke relevant konverterer en streng til et helt tal ( C99 ) ('atoi' betyder 'ASCII til heltal')
strtof( C99 )
strtod
strtold( C99 )
wcstof( C99 )
wcstod
wcstold( C99 )
konverterer en streng til en floating-point værdi
strtol
strtoll
wcstol
wcstoll
konverterer en streng til et signeret heltal
strtoul
strtoull
wcstoul
wcstoull
konverterer en streng til et usigneret heltal
  1. ^ Herrefererer streng enten til byte -streng eller bred streng

C -standardbiblioteket indeholder flere funktioner til numeriske konverteringer. De funktioner, der omhandler byte -strenge, er defineret i stdlib.hheaderen ( cstdlibheader i C ++). De funktioner, der beskæftiger sig med brede strenge, er defineret i wchar.hheaderen ( cwcharheader i C ++).

De strtoxxxfunktioner er ikke konst-korrekt , da de accepterer en conststreng pointer og returnere en ikke constpointer inden strengen.

Siden det normative ændringsforslag 1 (C95) anses atoxxfunktioner også for at være subsumerede af strtoxxxfunktioner, hvorfor hverken C95 eller nogen senere standard giver versioner med bred karakter af disse funktioner. Argumentet imod atoxxer, at de ikke skelner mellem en fejl og en 0.

Populære udvidelser

Navn Platform Beskrivelse
bzero POSIX , BSD Fylder en buffer med nul bytes, forældet med memset
memccpy SVID , POSIX kopierer op til et bestemt antal bytes mellem to hukommelsesområder, som ikke må overlappe hinanden, og stopper, når der findes en given byte.
mempcpy GNU en variant af at memcpyreturnere en markør til byten efter den sidste skrevne byte
strcasecmp POSIX, BSD case-ufølsomme versioner af strcmp
strcat_s Windows en variant strcatder kontrollerer destinationsbufferstørrelsen før kopiering
strcpy_s Windows en variant strcpyder kontrollerer destinationsbufferstørrelsen før kopiering
strdup POSIX tildeler og duplikerer en streng
strerror_r POSIX 1, GNU en variant af strerrordet er trådsikker. GNU -versionen er inkompatibel med POSIX one.
stricmp Windows case-ufølsomme versioner af strcmp
strlcpy BSD, Solaris en variant af strcpydet afkorter resultatet til at passe i destinationsbufferen
strlcat BSD, Solaris en variant af strcatdet afkorter resultatet til at passe i destinationsbufferen
strsignal POSIX: 2008 returnerer strengrepræsentation af en signalkode . Ikke trådsikker.
strtok_r POSIX en variant af strtokdet er trådsikker

Udskiftninger

På trods af det veletablerede behov for at udskifte strcatog strcpymed funktioner, der ikke tillader bufferoverløb, er der ikke opstået nogen accepteret standard. Dette skyldes delvist den fejlforståede tro hos mange C -programmører, der strncatog strncpyhar den ønskede adfærd; dog var ingen af ​​funktionerne designet til dette (de var beregnet til at manipulere nullpolstrede stringbuffere med fast størrelse, et dataformat, der er mindre almindeligt brugt i moderne software), og adfærd og argumenter er ikke-intuitive og ofte skrevet forkert, selv af ekspert programmører.

Den mest populære udskiftning er de strlcatog strlcpyfunktioner, der udkom i OpenBSD 2.4 i december, 1998. Disse funktioner altid skrive en NUL til destinationen buffer, beskærer resultatet, hvis det er nødvendigt, og returnere størrelsen af buffer, der vil være behov for, som gør det muligt detektion af afkortningen og giver en størrelse til oprettelse af en ny buffer, der ikke afkortes. De er blevet kritiseret på grundlag af angiveligt at være ineffektive, tilskynde til brug af C -strenge (i stedet for en overlegen alternativ form for streng) og skjule andre potentielle fejl. Derfor er de ikke inkluderet i GNU C -biblioteket (bruges af software på Linux), selvom de er implementeret i C -bibliotekerne til OpenBSD, FreeBSD , NetBSD , Solaris , OS X og QNX samt i alternative C -biblioteker til Linux, såsom musl introduceret i 2011. Manglen på GNU C biblioteksunderstøttelse har ikke forhindret forskellige softwareforfattere i at bruge det og samle en erstatning, blandt andet SDL , GLib , ffmpeg , rsync og endda internt i Linux -kernen . Open source -implementeringer til disse funktioner er tilgængelige.

Nogle gange memcpyeller memmovebruges, da de kan være mere effektive, end strcpyda de ikke gentagne gange tjekker NUL (dette er mindre sandt på moderne processorer). Da de har brug for en bufferlængde som parameter, kan korrekt indstilling af denne parameter undgå bufferoverløb.

Som en del af sin sikkerhedsudviklingslivscyklus fra 2004 introducerede Microsoft en familie af "sikre" funktioner, herunder strcpy_sog strcat_s(sammen med mange andre). Disse funktioner blev standardiseret med nogle mindre ændringer som en del af valgfri C11 (bilag K) foreslået af ISO/IEC WDTR 24731. Disse funktioner udfører forskellige kontroller, herunder om strengen er for lang til at passe i bufferen. Hvis kontrollerne mislykkes, kaldes en brugerspecificeret "runtime-constraint handler" -funktion, som normalt afbryder programmet. Nogle funktioner udfører ødelæggende operationer, før de ringer til runtime-constraint handler; f.eks. strcat_sindstiller destinationen til den tomme streng, hvilket kan gøre det svært at gendanne fra fejltilstande eller fejlsøge dem. Disse funktioner tiltrak betydelig kritik, fordi de oprindeligt kun blev implementeret på Windows, og samtidig begyndte at blive produceret advarselsmeddelelser fra Microsoft Visual C ++, hvilket foreslog, at programmørerne brugte disse funktioner i stedet for standardfunktioner. Dette er blevet spekuleret af nogle for at være et forsøg fra Microsoft på at låse udviklere til sin platform. Selvom open-source implementeringer af disse funktioner er tilgængelige, findes disse funktioner ikke i almindelige Unix C-biblioteker. Erfaring med disse funktioner har vist betydelige problemer med deres anvendelse og fejl i brugen, så fjernelse af bilag K foreslås til den næste revision af C -standarden. Brug af memset_ser også blevet foreslået som en måde at undgå uønskede kompileroptimeringer.

Se også

Noter

Referencer

eksterne links