C strenghåndtering - C string handling
C standardbibliotek |
---|
Generelle emner |
Diverse overskrifter |
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 NUL
tegn (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 \0
i 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 ( char
eller 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_t
er mindst 16 bit, og derfor kan alle 16-bit kodninger, såsom UCS-2 , gemmes. Hvis wchar_t
er 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_t
og 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_t
ikke 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_t
er 16 bits. Afkortning af strenge med tegn med variabel længde ved hjælp af funktioner som f.eks. strncpy
Kan 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 char
hvor kompilatorer bare kan kopiere, hvad der er mellem citaterne. Nogle kompilatorer eller redaktører kræver, at alle ikke-ASCII-tegn indtastes som \xNN
sekvenser for hver byte af UTF-8 og/eller \uNNNN
for 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.h
overskriften ( cstring
i C ++), mens funktioner, der fungerer på C -brede strenge, er deklareret i wchar.h
overskriften ( cwchar
i 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.h
er 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 const
strengmarkør og returnere en ikke- const
peger 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 str
præ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 | |
|
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 |
|
C -standardbiblioteket indeholder flere funktioner til numeriske konverteringer. De funktioner, der omhandler byte -strenge, er defineret i stdlib.h
headeren ( cstdlib
header i C ++). De funktioner, der beskæftiger sig med brede strenge, er defineret i wchar.h
headeren ( cwchar
header i C ++).
De strtoxxx
funktioner er ikke konst-korrekt , da de accepterer en const
streng pointer og returnere en ikke const
pointer inden strengen.
Siden det normative ændringsforslag 1 (C95) anses atoxx
funktioner også for at være subsumerede af strtoxxx
funktioner, hvorfor hverken C95 eller nogen senere standard giver versioner med bred karakter af disse funktioner. Argumentet imod atoxx
er, 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 memcpy returnere en markør til byten efter den sidste skrevne byte
|
strcasecmp
|
POSIX, BSD | case-ufølsomme versioner af strcmp
|
strcat_s
|
Windows | en variant strcat der kontrollerer destinationsbufferstørrelsen før kopiering
|
strcpy_s
|
Windows | en variant strcpy der kontrollerer destinationsbufferstørrelsen før kopiering
|
strdup
|
POSIX | tildeler og duplikerer en streng |
strerror_r
|
POSIX 1, GNU | en variant af strerror det er trådsikker. GNU -versionen er inkompatibel med POSIX one.
|
stricmp
|
Windows | case-ufølsomme versioner af strcmp
|
strlcpy
|
BSD, Solaris | en variant af strcpy det afkorter resultatet til at passe i destinationsbufferen
|
strlcat
|
BSD, Solaris | en variant af strcat det 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 strtok det er trådsikker
|
Udskiftninger
På trods af det veletablerede behov for at udskifte strcat
og strcpy
med 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 strncat
og strncpy
har 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 strlcat
og strlcpy
funktioner, 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 memcpy
eller memmove
bruges, da de kan være mere effektive, end strcpy
da 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_s
og 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_s
indstiller 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_s
er også blevet foreslået som en måde at undgå uønskede kompileroptimeringer.
Se også
- C -syntaks § Strenge - kildekodesyntaks, inklusive tilbageskridt -flugtsekvenser
- String funktioner
Noter
Referencer
eksterne links
- Hurtig memcpy i C , flere C -kodeeksempler til målretning af forskellige typer CPU -instruktionsarkitekturer