C - tyyppinen järjestelmä on tietotyypin konseptin toteutus C - ohjelmointikielessä . Kieli itsessään tarjoaa perusaritmeettiset tyypit sekä syntaksin taulukoiden ja yhdistelmätyyppien luomiseen. Jotkut C-standardin kirjaston otsikkotiedostot sisältävät tyyppimääritelmiä lisäominaisuuksilla [1] [2] .
C-kieli tarjoaa monia perustyyppejä. Suurin osa niistä on muodostettu käyttämällä yhtä neljästä aritmeettisesta tyyppimääritteestä ( char, int, floatja double) ja valinnaisista määritteistä ( signed, unsigned, shortja long). Vaikka standardi määrittää kaavasta lasketun alueen −(2 n−1 −1) - 2 n−1 −1 , kaikki tunnetut kääntäjät ( gcc , clang ja Microsoft - kääntäjä ) sallivat alueen − ( 2n−1 ) arvoon 2 n −1 −1 , missä n on tyypin bittileveys.
Alla olevassa taulukossa oletetaan, että 1 tavu = 8 bittiä.
Suurimmalla osalla nykyaikaisista alustoista tämä pitää paikkansa, mutta on mahdollista, että 1 tavu vastaa 16 bittiä tai jotain muuta numeroa, yleensä kahden potenssi.
Tyyppi | Selitys | Muodin määrittäjä |
---|---|---|
char | Kokonaisluku, pienin mahdollinen osoitteellinen tyyppi. Saattaa sisältää perusmerkkisarjan. Voi olla joko allekirjoitettu tai allekirjoittamaton, toteutus riippuu. Sisältää CHAR_BIT(yleensä 8) bittiä. [3] | %c |
signed char | Sama koko kuin char, mutta taatusti signeerattu. Voi ottaa arvoja ainakin alueelta [−127, +127][3] , yleensä toteutuksissa [4][−128, +127] | %c (myös %dtai %hhi( %hhx, %hho) numeerista tulosta varten) |
unsigned char | Sama koko kuin char, mutta taatusti allekirjoittamaton. Alue: [3] . Yleensä,[0, 2CHAR_BIT − 1][0, 255] | %c (tai %hhunumeerista tulosta varten) |
short short int signed short signed short int |
Merkillisen lyhyen kokonaisluvun tyyppi . Saattaa sisältää numeroita vähintään alueelta [−32767, +32767][3] , tyypillisesti [4] toteutuksissa . Joten se on vähintään 16 bittiä (2 tavua).[−32768, +32767] | %hi |
unsigned short unsigned short int |
Sama kuin shortmutta allekirjoittamaton. Alue:[0, +65535] | %hu |
int signed signed int |
Etumerkillisen kokonaisluvun perustyyppi. Voi sisältää numeroita vähintään alueelta [−32767, +32767][3] . Joten se on vähintään 16 bittiä (2 tavua). Tyypillisesti 4 tavua kokoa ja aluetta nykyaikaisissa kääntäjissä 32-bittisille ja uudemmille alustoille [−2 147 483 648, +2 147 483 647], mutta tyypillisesti 2 tavua 16- ja 8-bittisillä alustoilla [−32768, +32767], mikä aiheuttaa usein sekaannusta ja huonosti kirjoitetun koodin yhteensopimattomuutta. | %itai%d |
unsigned unsigned int |
Sama kuin intmutta allekirjoittamaton. Alue:[0, +4 294 967 295] | %u |
long long int signed long signed long int |
Merkitty pitkä kokonaislukutyyppi . Voi sisältää numeroita vähintään alueella [−2 147 483 647, +2 147 483 647]. [3] [4] [5] Se on siis vähintään 32 bittiä (4 tavua). | %litai%ld |
unsigned long unsigned long int |
Sama kuin longmutta allekirjoittamaton. Alue:[0, +4 294 967 295] | %lu |
long long long long int signed long long signed long long int |
Pitkä pitkä ( double long ) etumerkillinen kokonaislukutyyppi. Voi sisältää numeroita vähintään alueella [−9 223 372 036 854 775 808, +9 223 372 036 854 775 807]. [3] [4] Se on siis vähintään 64 bittiä. Hyväksytty standardissa C99 . |
%llitai%lld |
unsigned long long unsigned long long int |
Samanlainen, long longmutta allekirjoittamaton. Alue: [0, 18 446 744 073 709 551 615]. | %llu |
float | Todellinen liukulukutyyppi, jota kutsutaan yleisesti yhden tarkkuuden liukulukutyypiksi. Yksityiskohtaisia ominaisuuksia ei ole määritelty standardissa (lukuun ottamatta vähimmäisrajoja), mutta useimmissa järjestelmissä se on IEEE 754 yhden tarkkuuden liukulukubinäärimuoto . Tämä muoto vaaditaan valinnaisessa liitteen F "IEC 60559 liukulukuaritmeettisessa" liukulukuaritmeettisessa menetelmässä. | %f (muunnettu automaattisesti doublemuotoon printf()) |
double | Todellinen liukulukutyyppi, jota kutsutaan yleisesti kaksinkertaisen tarkkuuden liukulukutyyppiksi. Useimmissa järjestelmissä se on IEEE 754:n kaksinkertaisen tarkkuuden binääriliukulukumuotoa yhteensopiva . | %f( %F)
( %lf( %lF) varten scanf()) |
long double | Todellinen liukulukutyyppi, joka yleensä kartoitetaan suuren tarkkuuden liukulukumuotoon. Toisin kuin ja , voivat olla 80-bittinen liukuluku, ei-IEEE "double-double" tai "IEEE 754 nelitarkkuuden binääriliukuluku". Jos tarkempaa muotoa ei ole annettu, vastaa . Katso lisätietoja pitkästä tuplaa koskevasta artikkelista .floatdoubledouble | %Lf %LF %Lg %LG %Le %LE[6] |
Seuraavia tyyppimäärityksiä ei myöskään mainittu: ( %smerkkijonoille, %posoittimille, %x( %X) heksadesimaalimuodolle, %ooktaalille.
Kokonaislukutyyppien todellinen koko riippuu toteutuksesta. Standardi määrää vain tyyppien välisen koon suhteen ja kunkin tyypin vähimmäiskehyksen:
Ei siis long longsaa olla vähemmän long, mikä puolestaan ei saa olla vähemmän int, mikä puolestaan ei saa olla pienempi short. Koska char se on pienin mahdollinen osoitettava tyyppi, mikään muu tyyppi ei voi olla sitä pienempi.
Minimikoko for char on 8 bittiä, for shortja int on 16 bittiä, for long on 32 bittiä ja for long long on 64 bittiä.
On toivottavaa, että tyyppi inton kokonaislukutyyppi, jonka kanssa prosessori toimii tehokkaimmin. Tämä mahdollistaa suuren joustavuuden, esimerkiksi kaikki tyypit voivat olla 64-bittisiä. On kuitenkin olemassa suosittuja malleja, jotka kuvaavat kokonaislukutyyppien kokoa. [7]
Käytännössä tämä tarkoittaa, että se charvie 8 bittiä 16 bitin sijasta short(kuten niiden allekirjoittamattomat vastineet). intuseimmilla nykyaikaisilla alustoilla se vie 32 bittiä long long64 bitin sijaan. Pituus longvaihtelee: Windowsissa se on 32 bittiä, UNIXin kaltaisissa järjestelmissä 64 bittiä.
C99 - standardi sisältää uusia reaalityyppejä: float_tja double_t, määritelty kohdassa <math.h>. Se sisältää myös monimutkaisia tyyppejä: float _Complex, double _Complex, long double _Complex.
Boolen tyyppi lisättiin C99 : ään _Bool. Lisäksi ylimääräinen otsikkotiedosto <stdbool.h>määrittää sille aliaksen boolsekä makrot true(tosi) ja false(false). _Boolkäyttäytyy aivan kuten normaali sisäänrakennettu tyyppi, yhtä poikkeusta lukuun ottamatta: mikä tahansa ei-nolla (ei-false) määritys _Booltallennetaan ykkösenä. Tämä toiminta suojaa ylivuodolta. Esimerkiksi:
etumerkitön merkki b = 256 ; jos ( b ) { /* tee jotain */ }bkatsotaan vääräksi, jos se unsigned charkestää 8 bittiä. Tyypin vaihtaminen tekee muuttujasta kuitenkin tosi:
_Bool b = 256 ; jos ( b ) { /* tee jotain */ }C-kielen määrittely sisältää tyyppimerkinnät (typedef) size_tja ptrdiff_t. Niiden koko määräytyy suhteessa prosessorin aritmeettisiin ominaisuuksiin. Molemmat näistä tyypeistä on määritelty <stddef.h>( cstddefC++:lle).
size_t on etumerkitön kokonaislukutyyppi, joka on suunniteltu edustamaan minkä tahansa objektin kokoa muistissa (mukaan lukien taulukot) tietyssä toteutuksessa. Operaattori sizeofpalauttaa tyypin arvon size_t. Suurin koko size_tkirjoitetaan makrovakioon, joka on SIZE_MAXmääritelty <stdint.h>( cstdintC++:lle). size_ton oltava vähintään 16 bittiä. Lisäksi POSIX sisältää ssize_t, joka on sisäänrakennettu signed-tyyppinen koko size_t.
ptrdiff_t on sisäänrakennettu allekirjoitettu tyyppi, joka määrittää osoittimien välisen eron. Se toimii taatusti samantyyppisillä osoittimilla. Aritmetiikka erityyppisten osoittimien välillä riippuu toteutuksesta.
Tietoa sisäänrakennettujen perustyyppien todellisista ominaisuuksista, kuten koosta, saadaan makrovakioiden kautta kahdessa otsikossa: otsikko <limits.h>( climitsC++:ssa) määrittää makrot kokonaislukutyypeille, otsikko <float.h>( cfloatC++:ssa) määrittää makrot todellisille tyypeille. Tietyt arvot riippuvat toteutuksesta.
Kokonaislukutyyppien ominaisuudetC99-standardi sisältää määritelmiä useille uusille kokonaislukutyypeille ohjelman siirrettävyyden parantamiseksi. [2] Jo saatavilla olevia kokonaislukukantatyyppejä pidettiin epätyydyttävinä, koska niiden koko riippui toteutuksesta. Uusia tyyppejä käytetään laajalti sulautetuissa järjestelmissä. Kaikki uudet tyypit määritellään otsikkotiedostossa <inttypes.h>( cinttypesC++:ssa) ja ne ovat saatavilla myös <stdint.h>( cstdintC++:ssa). Tyypit voidaan jakaa seuraaviin luokkiin:
Seuraava taulukko näyttää nämä tyypit ( N tarkoittaa bittien määrää):
Tyyppiluokka | Signeeratut tyypit | Allekirjoittamattomat tyypit | ||||
---|---|---|---|---|---|---|
Tyyppi | Minimiarvo | Suurin arvo | Tyyppi | Minimiarvo | Suurin arvo | |
Tarkka koko | intN_t | INTN_MIN | INTN_MAX | uintN_t | 0 | UINTN_MAX |
Minimikoko | int_leastN_t | INT_LEASTN_MIN | INT_LEASTN_MAX | uint_leastN_t | 0 | UINT_LEASTN_MAX |
nopein | int_fastN_t | INT_FASTN_MIN | INT_FASTN_MAX | uint_fastN_t | 0 | UINT_FASTN_MAX |
Osoitin | intptr_t | INTPTR_MIN | INTPTR_MAX | uintptr_t | 0 | UINTPTR_MAX |
Suurin koko | intmax_t | INTMAX_MIN | INTMAX_MAX | uintmax_t | 0 | UINTMAX_MAX |
Otsikkotiedosto <inttypes.h>( cinttypesC++:ssa) laajentaa kohdassa määriteltyjen tyyppien ominaisuuksia <stdint.h>. Ne sisältävät makroja, jotka määrittävät tyyppimäärityksiä printf- ja scanf-muotoisille merkkijonoille, ja useita toimintoja, jotka toimivat intmax_tja -tyypeillä uintmax_t. Tämä otsikkotiedosto lisättiin C99 :ssä .
printf-muotoinen merkkijonoMakrot määritellään muodossa . Tässä {fmt} tarkoittaa tulostusmuotoa ja kuuluu arvoihin (desimaali), (heksadesimaali), (oktaali), (allekirjoittamaton) tai (kokonaisluku). {type} määrittää argumentin tyypin ja kuuluu ryhmään , , , tai , missä on bittien määrä. PRI{fmt}{type}dxouiNFASTNLEASTNPTRMAXN
scanf-muotoinen merkkijonoMakrot määritellään muodossa . Tässä {fmt} tarkoittaa tulostusmuotoa ja kuuluu arvoihin (desimaali), (heksadesimaali), (oktaali), (allekirjoittamaton) tai (kokonaisluku). {type} määrittää argumentin tyypin ja kuuluu ryhmään , , , tai , missä on bittien määrä. SCN{fmt}{type}dxouiNFASTNLEASTNPTRMAXN
ToiminnotC:n rakenteiden avulla voit tallentaa useita kenttiä yhteen muuttujaan. Voidaan kutsua tietueiksi tai monikoiksi muilla kielillä. Tämä rakenne tallentaa esimerkiksi henkilön nimen ja syntymäajan:
rakentaa syntymäpäivä { char nimi [ 20 ]; int päivä ; int kuukausi ; int vuosi ; };Ohjelman rungon rakennemääritykset on aina aloitettava avainrakenteella (valinnainen C++:ssa). Rakenteen jäseniin pääsee käsiksi operaattorilla . tai -> , jos työskentelemme rakenteeseen osoittavan osoittimen kanssa. Rakenteet voivat sisältää osoittimia itseensä, mikä mahdollistaa useiden tietorakenteiden toteuttamisen linkitettyjen listojen perusteella. Tämä mahdollisuus saattaa tuntua ristiriitaiselta, mutta kaikki osoittimet vievät saman määrän tavuja, joten tämän kentän koko ei muutu rakennekenttien määrän mukaan.
Rakenteet eivät aina vie sitä tavumäärää, joka on yhtä suuri kuin niiden elementtien tavujen summa. Kääntäjä normaalisti kohdistaa elementit 4 tavun lohkoihin. On myös mahdollista rajoittaa tietylle kentälle allokoitujen bittien määrää, tätä varten sinun on määritettävä kentän koko bitteinä kentän nimen jälkeen kaksoispisteellä erotettuna. Tämän ominaisuuden avulla voit luoda bittikenttiä .
Joitakin rakenteiden ominaisuuksia:
Jokaiselle T -tyypille , paitsi void- ja funktiotyypeille, on " N tyypin T elementin joukko ". Taulukko on kokoelma samantyyppisiä arvoja, jotka on tallennettu peräkkäin muistiin. N - kokoinen taulukko indeksoidaan kokonaisluvulla 0 - N-1 . Myös taulukot ovat mahdollisia, joiden koko on kääntäjälle tuntematon. Taulukon koon on oltava vakio. Esimerkkejä
int cat [ 10 ] = { 5 , 7 , 2 }; // 10 elementin matriisi, kunkin tyyppiä int int bob []; // taulukko, jossa on tuntematon määrä elementtejä tyyppiä "int".Matriisit voidaan alustaa alustusluettelolla, mutta niitä ei voi määrittää toisilleen. Taulukot välitetään funktioille käyttämällä osoitinta ensimmäiseen elementtiin (taulukon nimi on ensimmäisen elementin osoite). Moniulotteiset taulukot ovat taulukoiden taulukoita. Esimerkkejä:
int a [ 10 ][ 8 ]; // 10 elementin taulukko, kukin tyyppiä '8 int elementin taulukko' float f [][ 32 ] = {{ 0 },{ 4 , 5 , 6 }};Kaikille T -tyypeille on tyyppi "osoitin T ".
Muuttujat voidaan ilmoittaa osoittimina erityyppisiin arvoihin käyttämällä *. Jos haluat määrittää muuttujan tyypin osoittimeksi, sen nimen eteen on lisättävä tähti.
char kirjain C = 'C' ; char * kirjain = & kirjain C ; //otetaan kirjaimen C osoite ja määritetään kirjaimelle printf ( "Tämä koodi on kirjoitettu %c." , * kirjain ); //"Tämä koodi on kirjoitettu C-kielellä."Vakiotyyppien lisäksi voit ilmoittaa osoittimia rakenteille ja liitoksille:
struct Piste { int x , y ; } A ; A. _ x = 12 ; A. _ y = 34 _ struct Piste * p = & A ; printf ( "X: %d, Y: %d" , ( * p ). x , ( * p ). y ); //"X: 12, Y: 34"Rakenteen kenttiin pääsemiseksi osoittimella on nuolioperaattori , joka on ->synonyymi edellisen merkinnän kanssa: (*p).x - sama kuin p->x.
Koska osoitin on myös muuttujatyyppi, sääntö "mikä tahansa tyyppi T " pätee myös niille: voit ilmoittaa osoittimia osoittimille. Voit esimerkiksi käyttää int***:
int w = 100 ; int * x = & w ; int ** y = & x ; int *** z = & y ; printf ( "w sisältää %d." , *** z ); //"w sisältää 100."Siellä on myös osoittimia taulukoihin ja funktioihin. Taulukkoosoittimilla on seuraava syntaksi:
char * pc [ 10 ]; // 10 osoittimen joukko char char ( * pa )[ 10 ]; // osoitin 10 char-muuttujan taulukkoonpc - joukko osoittimia, jotka vievät 10 * sizeof(char*)tavun (yleisillä alustoilla - yleensä 40 tai 80 tavua), ja pa - tämä on yksi osoitin; se vie yleensä 4 tai 8 tavua, mutta sen avulla voit käyttää taulukkoa, joka vie 10 tavua: sizeof(pa) == sizeof(int*)mutta sizeof(*pa) == 10 * sizeof(char). Osoittimet taulukoihin eroavat osoittimista ensimmäiseen elementtiin aritmetiikassa. Jos osoittimet paosoittavat esimerkiksi osoitteeseen 2000, osoitin pa+1osoittaa osoitteeseen 2010.
char ( * pa )[ 10 ]; char array [ 10 ] = "Wikipedia" ; pa = & array ; printf ( "Esimerkki kohteelle %s. \n " , * pa ); //"Esimerkki Wikipediaan." printf ( "%c %c %c" , ( * pa )[ 1 ], ( * pa )[ 3 ], ( * pa )[ 7 ]); //"ii minä"Liitot ovat erityisiä rakenteita, joiden avulla eri kentät voivat jakaa yhteisen muistin. Näin ollen vain yksi kentistä voidaan tallentaa liittoon. Liiton koko on yhtä suuri kuin suurimman kentän koko. Esimerkki:
liitto { int i ; kellua f ; struct { allekirjoittamaton int u ; kaksinkertainen d ; } s ; } u ;Yllä olevassa esimerkissä ukoko on (jonka koko on ja u.ssumma ), koska s on suurempi kuin ja . Liitosta lukeminen ei sisällä tyyppimuunnoksia. u.s.uu.s.dif
Enumien avulla voit määrittää mukautettuja tyyppejä koodiisi. Esimerkki:
enum { punainen , vihreä = 3_ _ sininen } väri ;Enumit parantavat koodin luettavuutta, mutta eivät ole tyyppiturvallisia (esim. järjestelmälle 3 ja vihreä ovat sama asia. C ++:ssa otettiin käyttöön enum-luokat tämän puutteen korjaamiseksi), koska ne ovat kokonaislukuja. Tässä esimerkissä punaisen arvo on nolla ja sinisen arvo on neljä.
Toimintoosoittimien avulla voit siirtää funktion toiseen ja toteuttaa takaisinsoittomekanismin . Funktioosoittimien avulla voit viitata funktioihin tietyllä allekirjoituksella. Esimerkki osoittimen luomisesta funktioon abs, joka ottaa int:n ja palauttaa int:n nimeltä my_int_f:
int ( * my_int_f )( int ) = & abs ; // &-operaattori on valinnainen, mutta tekee sen selväksi osoittamalla nimenomaisesti, että välitämme osoitteenToimintoosoittimia kutsutaan nimellä kuten normaaleja funktiokutsuja. Toimintoosoittimet ovat erillisiä tavallisista osoittimista ja osoittimista mitättömiin.
Monimutkaisempi esimerkki:
char ret_a ( int x ) { return 'a' + x ; } typedef char ( * fptr )( int ); fptr other_func ( float a ) { paluu & ret_a ; }Tässä olemme luoneet mukavuussyistä aliaksen nimeltä fptr osoittimelle funktioon, joka palauttaa merkin ja ottaa int:n. Ilman typedefiä syntaksia olisi vaikeampi lukea:
char ret_a ( int x ) { return 'a' + x ; } char ( * func ( float a , int b ))( int ) { char ( * fp )( int ) = & ret_a ; paluu fp ; } char ( * ( * superfunc ( double a ))( float , int ))( int ) { char ( * ( * fpp )( float , int ))( int ) =& func ; paluu fpp ; }Func-funktio ei palauta merkkiä, kuten se saattaa näyttää, vaan osoittimen funktioon, joka palauttaa merkin ja hyväksyy int. Ja hyväksyy float ja int.
Yllä olevilla tyypeillä voi olla erilaisia tyyppimääritteitä. C11 -standardin mukaan on neljä tyyppiä:
Myös standardista 99 lähtien funktion tarkenne on lisätty inline, mikä on vihje kääntäjälle sisällyttää koodi funktion rungosta itse funktion kutsumisen sijaan.
Yhdellä muuttujalla voi olla useita tarkenteita. Esimerkki:
const haihtuva int a = 5 ; volatile int const * b = &a ; //osoitin const volatile int int * const c = NULL ; // const osoitin intC:ssä on myös neljä säilytysluokkaa:
C-ohjelmointikieli | |
---|---|
Kääntäjät |
|
Kirjastot | |
Erikoisuudet | |
Jotkut jälkeläiset | |
C ja muut kielet |
|
Luokka: C-ohjelmointikieli |