A C típusú rendszer az adattípus koncepciójának megvalósítása a C programozási nyelvben . Maga a nyelv alapvető aritmetikai típusokat, valamint szintaxist biztosít tömbök és összetett típusok létrehozásához. Néhány fejlécfájl a C szabványkönyvtárból további tulajdonságokkal rendelkező típusdefiníciókat tartalmaz [1] [2] .
A C nyelv számos alapvető típust kínál. Legtöbbjük a négy aritmetikai típusmeghatározó ( char, int, floatés double), valamint az opcionális specifikációk ( signed, unsigned, shortés long) valamelyikével jön létre. Bár a szabvány a képletből kiszámított tartományt ad meg −(2 n−1 −1) és 2 n−1 −1 között, az összes ismert fordító ( gcc , clang és Microsoft fordító ) engedélyezi a − (2 n−1 ) tartományt. 2 n −1 −1 - re , ahol n a típus bitszélessége.
Az alábbi táblázat feltételezi, hogy 1 bájt = 8 bit.
A modern platformok túlnyomó többségén ez igaz, de lehetséges, hogy 1 bájt 16 bitnek vagy más számnak felel meg, általában kettő hatványa.
Típusú | Magyarázat | Formátummeghatározó |
---|---|---|
char | Egész szám, a lehető legkisebb címezhető típus. Tartalmazhatja az alap karakterkészletet. Lehet aláírt vagy aláíratlan, megvalósításfüggő. CHAR_BIT(általában 8) bitet tartalmaz . [3] | %c |
signed char | Ugyanolyan méretű, mint a char, de garantáltan aláírják. Legalább a [−127, +127][3] tartományból tud értékeket venni , általában implementációkban [4][−128, +127] | %c ( %dvagy %hhi( %hhx, %hho) is a numerikus kimenethez) |
unsigned char | Mérete megegyezik a mérettel char, de garantáltan aláírás nélkül lesz. Tartomány: [3] . Általában,[0, 2CHAR_BIT − 1][0, 255] | %c (vagy %hhunumerikus kimenethez) |
short short int signed short signed short int |
Előjeles rövid egész szám típusa . Tartalmazhat számokat legalább a [−32767, +32767][3] tartományból , jellemzően a [4] megvalósításokban . Tehát legalább 16 bites (2 bájt).[−32768, +32767] | %hi |
unsigned short unsigned short int |
Ugyanaz, mint, shortde aláírás nélkül. Hatótávolság:[0, +65535] | %hu |
int signed signed int |
Az előjeles egész szám alaptípusa. Tartalmazhat számokat legalább a [−32767, +32767][3] tartományból . Tehát legalább 16 bites (2 bájt). Általában 4 bájt méretű és tartományú a modern fordítóknál 32 bites és magasabb platformokon [−2 147 483 648, +2 147 483 647], de jellemzően 2 bájt tartomány 16 és 8 bites platformokon [−32768, +32767], ami gyakran okoz zavart és összeférhetetlenséghez vezet a rosszul megírt kód | %ivagy%d |
unsigned unsigned int |
Ugyanaz, mint, intde aláírás nélkül. Hatótávolság:[0, +4 294 967 295] | %u |
long long int signed long signed long int |
Előjeles hosszú egész típusú . Legalább a tartományba eső számokat tartalmazhat [−2 147 483 647, +2 147 483 647]. [3] [4] [5] Tehát legalább 32 bites (4 bájt). | %livagy%ld |
unsigned long unsigned long int |
Ugyanaz, mint, longde aláírás nélkül. Hatótávolság:[0, +4 294 967 295] | %lu |
long long long long int signed long long signed long long int |
A long long ( double long ) előjeles egész típus. Legalább a tartományba eső számokat tartalmazhat [−9 223 372 036 854 775 808, +9 223 372 036 854 775 807]. [3] [4] Tehát legalább 64 bites. A C99 szabvány szerint jóváhagyva . |
%llivagy%lld |
unsigned long long unsigned long long int |
Hasonló, long longde aláíratlan. Tartomány: [0, 18 446 744 073 709 551 615]. | %llu |
float | Valós lebegőpontos számtípus, amelyet általában egyszeres pontosságú lebegőpontos számtípusnak neveznek. A szabvány nem határozza meg a részletes tulajdonságokat (kivéve a minimális határértékeket), de a legtöbb rendszeren ez az IEEE 754 egypontos lebegőpontos bináris formátum . Ez a formátum szükséges az F. melléklet „IEC 60559 lebegőpontos aritmetika” lebegőpontos aritmetikához. | %f (automatikusan konvertálva erre double: printf()) |
double | Valódi lebegőpontos típus, amelyet általában dupla pontosságú lebegőpontos számtípusnak neveznek. A legtöbb rendszeren megfelel az IEEE 754 dupla pontosságú bináris lebegőpontos formátumnak . | %f( %F)
( %lf( %lF) for scanf()) |
long double | Valódi lebegőpontos számtípus, általában a nagy pontosságú lebegőpontos számformátumra van leképezve. Ellentétben a és -vel , lehet 80 bites lebegőpontos, nem IEEE "double-double" vagy "IEEE 754 négypontos bináris lebegőpontos". Ha nincs megadva pontosabb formátum, akkor egyenértékű a . A részletekért lásd a hosszú dupla cikket .floatdoubledouble | %Lf %LF %Lg %LG %Le %LE[6] |
A következő típusleírók szintén nem kerültek említésre: ( %skarakterláncokhoz, %pmutatókhoz, %x( %X) hexadecimális ábrázoláshoz, %ooktálishoz.
Az egész típusok tényleges mérete megvalósításfüggő. A szabvány csak a típusok közötti méretarányt és az egyes típusok minimális keretét írja elő:
Tehát long longnem lehet kevesebb long, ami viszont nem lehet kevesebb int, ami viszont nem lehet kevesebb short. Mivel char ez a lehető legkisebb címezhető típus, más típus nem lehet ennél kisebb.
A minimális mérete char 8 bit, for shortés int 16 bit, for long 32 bit, for long long pedig 64 bit.
Kívánatos, hogy a típus intolyan egész típusú legyen, amellyel a processzor a leghatékonyabban dolgozik. Ez nagy rugalmasságot tesz lehetővé, például minden típus 64 bites lehet. Vannak azonban népszerű sémák, amelyek leírják az egész típusok méretét. [7]
A gyakorlatban ez azt jelenti, hogy 16 charbit helyett 8 bitet vesz igénybe short(akárcsak az előjel nélküli megfelelőik). inta legtöbb modern platformon 64 bit helyett 32 bitet vesz igénybe long long. A hossza longváltozó: Windowsnál 32 bites, UNIX-szerű rendszereknél 64 bites.
A C99 szabvány új valós típusokat tartalmaz: float_tés double_t-ban definiált <math.h>. Összetett típusokat is tartalmaz : float _Complex, double _Complex, long double _Complex.
A logikai típust hozzáadták a C99_Bool -hez . Ezenkívül egy további fejlécfájl <stdbool.h>álnevet bool, valamint makrókat true(igaz) és false(hamis) határoz meg. _Boolugyanúgy viselkedik, mint egy normál beépített típus, egy kivétellel: minden nem nulla (nem hamis) hozzárendelés _Boolegyként kerül tárolásra. Ez a viselkedés véd a túlcsordulás ellen. Például:
előjel nélküli karakter b = 256 ; if ( b ) { /* csinálj valamit */ }bhamisnak tekinthető, ha unsigned char8 bitet vesz igénybe. A típus megváltoztatása azonban igazzá teszi a változót:
_Bool b = 256 ; if ( b ) { /* csinálj valamit */ }A C nyelvi specifikáció tartalmazza a típusmegjelöléseket (typedef) size_tés ptrdiff_t. Méretük a processzor aritmetikai képességeihez viszonyítva van meghatározva. Mindkét típust a <stddef.h>( cstddefC++ esetén) határozza meg.
size_t egy előjel nélküli egész típus, amelyet arra terveztek, hogy a memóriában lévő objektumok méretét (beleértve a tömböket is) reprezentálja egy adott megvalósításban. Az operátor sizeofegy típusú értéket ad vissza size_t. A maximális méret size_tegy makróállandóba van írva, amelyet ( C++ esetén) SIZE_MAXdefiniálunk . legalább 16 bitesnek kell lennie. Ezenkívül a POSIX tartalmazza a , ami egy beépített, aláírt mérettípus . <stdint.h>cstdintsize_tssize_tsize_t
ptrdiff_t egy beépített aláírt típus, amely meghatározza a mutatók közötti különbséget. Garantáltan hat az azonos típusú mutatókra. A különböző típusú mutatók közötti aritmetika megvalósításfüggő.
Az alapvető beépített típusok tényleges tulajdonságairól, például méretéről, a makrókonstansokon keresztül két fejlécben adható információ: a fejléc <limits.h>( climitsC++-ban) egész típusú makrókat, a fejléc <float.h>( cfloatC++-ban) pedig a valós típusokhoz definiál makrókat. A konkrét értékek a megvalósítástól függenek.
Az egész típusok tulajdonságaiA C99 szabvány számos új egész típushoz tartalmaz definíciókat a programok hordozhatóságának javítása érdekében. [2] A már rendelkezésre álló egész számok alaptípusait nem tartották kielégítőnek, mert méretük megvalósításfüggő. Az új típusokat széles körben alkalmazzák a beágyazott rendszerekben. Minden új típus egy fejlécfájlban van definiálva <inttypes.h>( cinttypesC++-ban), és elérhető <stdint.h>( cstdintC++-ban is). A típusok a következő kategóriákra oszthatók:
Az alábbi táblázat ezeket a típusokat mutatja ( N a bitek számát jelenti):
Típuskategória | Aláírt típusok | Aláíratlan típusok | ||||
---|---|---|---|---|---|---|
Típusú | Minimális érték | Maximális érték | Típusú | Minimális érték | Maximális érték | |
Pontos méret | intN_t | INTN_MIN | INTN_MAX | uintN_t | 0 | UINTN_MAX |
Minimális méret | int_leastN_t | INT_LEASTN_MIN | INT_LEASTN_MAX | uint_leastN_t | 0 | UINT_LEASTN_MAX |
leggyorsabb | int_fastN_t | INT_FASTN_MIN | INT_FASTN_MAX | uint_fastN_t | 0 | UINT_FASTN_MAX |
Mutató | intptr_t | INTPTR_MIN | INTPTR_MAX | uintptr_t | 0 | UINTPTR_MAX |
Maximális méret | intmax_t | INTMAX_MIN | INTMAX_MAX | uintmax_t | 0 | UINTMAX_MAX |
A fejlécfájl <inttypes.h>( cinttypesC++ nyelven) kiterjeszti a -ban definiált típusok képességeit <stdint.h>. Ezek közé tartoznak a makrók, amelyek típusspecifikációkat határoznak meg a printf és scanf formátumú karakterláncokhoz, valamint számos olyan függvényt, amely a intmax_tés típusokon működik uintmax_t. Ez a fejlécfájl a C99 -ben lett hozzáadva .
printf formátumú karakterláncA makrók a következő formátumban vannak meghatározva . Itt az {fmt} a kimeneti formátumot jelenti, és a következőkhöz tartozik: (tizedes), (hexadecimális), (oktális), (előjel nélküli) vagy (egész szám). A {type} az argumentum típusát határozza meg, és a , , , vagy , ahol a bitek száma. PRI{fmt}{type}dxouiNFASTNLEASTNPTRMAXN
scanf formátumú karakterláncA makrók a következő formátumban vannak meghatározva . Itt az {fmt} a kimeneti formátumot jelenti, és a következőkhöz tartozik: (tizedes), (hexadecimális), (oktális), (előjel nélküli) vagy (egész szám). A {type} az argumentum típusát határozza meg, és a , , , vagy , ahol a bitek száma. SCN{fmt}{type}dxouiNFASTNLEASTNPTRMAXN
FunkciókA C-beli struktúrák lehetővé teszik több mező tárolását egyetlen változóban. Más nyelveken rekordoknak vagy soroknak nevezhető. Ez a struktúra például egy személy nevét és születési dátumát tárolja:
struct születésnapját { char név [ 20 ]; int nap ; int hónap ; int év ; };A programtörzsben a struktúradeklarációnak mindig a kulcsstruktúrával kell kezdődnie (C++-ban nem kötelező). A szerkezet tagjai az operátor segítségével érhetők el . vagy -> , ha egy szerkezetre mutató mutatóval dolgozunk. A struktúrák tartalmazhatnak mutatókat önmagukra, ami lehetővé teszi számos adatstruktúra megvalósítását linkelt listák alapján. Ez a lehetőség ellentmondásosnak tűnhet, de minden mutató ugyanannyi bájtot foglal el, így ennek a mezőnek a mérete nem változik a szerkezeti mezők számával.
A struktúrák nem mindig annyi bájtot foglalnak el, mint az elemeik bájtjainak összege. A fordító általában 4 bájtos blokkokba rendezi az elemeket. Lehetőség van egy adott mezőhöz lefoglalt bitek számának korlátozására is, ehhez meg kell adni a mező méretét bitekben a mező neve után kettősponttal elválasztva. Ez a funkció lehetővé teszi bitmezők létrehozását .
A szerkezetek néhány jellemzője:
Minden T típushoz , kivéve a void- és függvénytípusokat, létezik egy " N T típusú elemből álló tömb " típusú. A tömb azonos típusú értékek gyűjteménye , amelyeket szekvenciálisan tárolunk a memóriában. Egy N méretű tömböt egy 0 és N-1 közötti egész szám indexel . A fordító számára ismeretlen méretű tömbök is lehetségesek. Egy tömb méretének állandónak kell lennie. Példák
int cat [ 10 ] = { 5 , 7 , 2 }; // 10 elemből álló tömb, mindegyik int int bob [] típusú; // tömb ismeretlen számú 'int' típusú elemmel.A tömbök inicializálhatók inicializálási listával, de nem rendelhetők egymáshoz. A tömbök az első elemre mutató mutató segítségével kerülnek átadásra a függvényeknek (a tömb neve az első elem címe). A többdimenziós tömbök tömbök tömbjei. Példák:
int a [ 10 ][ 8 ]; // 10 elemből álló tömb, mindegyik '8 int elemből álló tömb' típusú float f [][ 32 ] = {{ 0 },{ 4 , 5 , 6 }};Bármely T típushoz van egy "pointer to T " típus.
A változók különféle típusú értékekre mutatókként* deklarálhatók a . Ahhoz, hogy egy változó típusát mutatóként definiálhassa, a neve előtt egy csillagot kell írni.
char betű C = 'C' ; char * betű = & betű C ; //a letterC címének felvétele és a printf betűhöz való hozzárendelése ( "Ez a kód %c-ben van írva." , * letter ); //"Ez a kód C-ben van írva."A szabványos típusokon kívül deklarálhat mutatókat struktúrákra és uniókra:
struct Pont { int x , y ; } A ; A. _ x = 12 ; A. _ y = 34_ _ struct Pont * p = & A ; printf ( "X: %d, Y: %d" , ( * p ). x , ( * p ). y ); //"X: 12, Y: 34"A struktúra mezőinek mutató segítségével történő eléréséhez van egy nyíl operátor ->, amely az előző bejegyzés szinonimája: (*p).x - ugyanaz, mint a p->x.
Mivel a mutató is egy változótípus, a „bármely T típusra” szabály rájuk is igaz: mutatókat deklarálhatunk a mutatókra. Például használhatja int***:
int w = 100 ; int * x = & w ; int ** y = & x ; int *** z = & y ; printf ( "w tartalmazza %d." , *** z ); //"w 100-at tartalmaz."Vannak mutatók a tömbökre és a függvényekre is. A tömbmutatók szintaxisa a következő:
char * pc [ 10 ]; // 10 mutatóból álló tömb a char char -ra ( * pa )[ 10 ]; // mutató egy 10 karakteres változóból álló tömbrepc - mutatók tömbje, amely egy bájtot foglal el 10 * sizeof(char*)(általános platformokon - általában 40 vagy 80 bájt), és pa - ez egy mutató; általában 4 vagy 8 bájtot foglal el, azonban lehetővé teszi a 10 bájtot elfoglaló tömb elérését: sizeof(pa) == sizeof(int*)de sizeof(*pa) == 10 * sizeof(char). A tömbökre mutató mutatók eltérnek az aritmetika első elemére mutató mutatóktól. Például, ha a mutató paa 2000-es címre mutat, akkor a mutató pa+1a 2010-es címre mutat.
char ( * pa )[ 10 ]; char array [ 10 ] = "Wikipédia" ; pa = & tömb ; printf ( "Példa a következőre: %s. \n " , * pa ); //"Példa a Wikipédiához." printf ( "%c %c %c" , ( * pa )[ 1 ], ( * pa )[ 3 ], ( * pa )[ 7 ]); //"ii i"Az uniók olyan speciális struktúrák, amelyek lehetővé teszik a különböző mezők számára, hogy közös memóriát osztozzanak. Így csak az egyik mező tárolható az unióban. Az unió mérete megegyezik a legnagyobb mező méretével. Példa:
szakszervezet { int i ; úszó f ; struct { unsigned int u ; dupla d ; } s ; } u ;A fenti példában ua méret u.s(melynek mérete a u.s.ués összege u.s.d), mivel s nagyobb, mint iés f. A szakszervezetből való olvasás nem jár típusátalakítással.
Az Enumok lehetővé teszik, hogy egyedi típusokat határozzon meg a kódban. Példa:
enum { piros , zöld = 3_ _ kék } szín ;Az enum-ok javítják a kód olvashatóságát, de nem típusbiztosak (pl. a 3 -as rendszernél és a zöld ugyanaz. A C ++-ban enum osztályokat vezettek be ennek a hiányosságnak a kijavítására), mivel ezek egész számok. Ebben a példában a piros értéke nulla, a kéké pedig négy.
A függvénymutatók lehetővé teszik az egyik függvény átadását a másiknak, és visszahívási mechanizmus megvalósítását . A függvénymutatók lehetővé teszik, hogy meghatározott aláírással rendelkező függvényekre hivatkozzon. Példa egy olyan függvényre mutató mutató létrehozására , amely egy int-et absvesz fel, és egy int nevű int-et ad vissza my_int_f:
int ( * my_int_f )( int ) = & abs ; // a & operátor nem kötelező, de egyértelművé teszi azáltal, hogy kifejezetten megmutatja, hogy címet adunk átA függvénymutatókat név szerint hívják, mint a normál függvényhívásokat. A függvénymutatók elkülönülnek a normál mutatóktól és az érvénytelen mutatóktól.
Bonyolultabb példa:
char ret_a ( int x ) { return 'a' + x ; } typedef char ( * fptr )( int ); fptr other_func ( float a ) { return & ret_a ; }Itt a kényelem kedvéért létrehoztunk egy fptr nevű álnevet egy olyan függvény mutatójához, amely egy char-ot ad vissza, és egy int-et vesz fel. A typedef nélkül a szintaxist nehezebb lenne elolvasni:
char ret_a ( int x ) { return 'a' + x ; } char ( * func ( float a , int b ))( int ) { char ( * fp )( int ) = & ret_a ; return fp ; } char ( * ( * superfunc ( double a ))( float , int ))( int ) { char ( * ( * fpp )( float , int ))( int ) =& func ; return fpp ; }A func függvény nem egy char-ot ad vissza, mint amilyennek látszik, hanem egy mutatót egy olyan függvényre, amely char-ot ad vissza, és elfogad egy int-et. És elfogadja az úszót és az int.
A fenti típusoknak különböző típusú minősítői lehetnek. A C11 szabvány szerint négy típusú minősítő létezik:
Szintén a 99 - es szabvány óta egy függvényminősítő is hozzáadásra került inline, ami arra utal, hogy a fordító a függvény törzséből származó kódot is belefoglalja, ahelyett, hogy magát a függvényt hívná meg.
Egy változónak több minősítője is lehet. Példa:
const illékony int a = 5 ; volatile int const * b = &a ; //mutató a const-ra volatile int int * const c = NULL ; // const mutató intA C-ben négy tárolási osztály is létezik:
C programozási nyelv | |
---|---|
Fordítók |
|
Könyvtárak | |
Sajátosságok | |
Néhány leszármazott | |
C és más nyelvek |
|
Kategória:C programozási nyelv |