Datové typy C - C data types
Standardní knihovna C. |
---|
Obecná témata |
Různé záhlaví |
V programovacím jazyce C , datové typy představují sémantiku a vlastnosti ukládání datových prvků. Jsou vyjádřeny v syntaxi jazyka ve formě deklarací pro umístění paměti nebo proměnné . Datové typy také určují typy operací nebo metody zpracování datových prvků.
Jazyk C poskytuje základní aritmetické typy, jako jsou celočíselné a reálné číselné typy, a syntaxi pro vytváření typů polí a sloučenin. Záhlaví pro standardní knihovnu C , která se má použít prostřednictvím zahrnout direktivy , obsahují definice typů podpory, které mají další vlastnosti, jako například poskytování úložiště s přesnou velikostí, nezávisle na jazykové implementaci na konkrétních hardwarových platformách.
Základní typy
Hlavní typy
Jazyk C poskytuje čtyři základní specifikátory aritmetických typů char , int , float a double a modifikátory signed , unsigned , short a long . Následující tabulka uvádí přípustné kombinace při určování velké sady deklarací specifických pro velikost úložiště.
Typ | Vysvětlení | Minimální velikost (bity) | Specifikátor formátu |
---|---|---|---|
char |
Nejmenší adresovatelná jednotka počítače, která může obsahovat základní znakovou sadu. Jedná se o celočíselný typ. Skutečný typ může být podepsaný nebo nepodepsaný. Obsahuje CHAR_BIT bitů. | 8 |
%c
|
signed char |
Stejné velikosti jako char , ale zaručeně podepsané. Může obsahovat alespoň rozsah [−127, +127]. | 8 |
%c (nebo %hhi pro numerický výstup)
|
unsigned char |
Stejné velikosti jako char , ale zaručeně bez znaménka. Obsahuje alespoň rozsah [0, 255]. | 8 |
%c (nebo %hhu pro numerický výstup)
|
short short int signed short signed short int
|
Krátký celočíselný typ se znaménkem. Může obsahovat alespoň rozsah [−32 767, +32 767]. | 16 |
%hi nebo %hd
|
unsigned short unsigned short int
|
Krátký celočíselný typ bez znaménka. Obsahuje alespoň rozsah [0, 65 535]. | 16 |
%hu
|
int signed signed int
|
Základní typ celého čísla se znaménkem. Může obsahovat alespoň rozsah [−32 767, +32 767]. | 16 |
%i nebo %d
|
unsigned unsigned int
|
Základní celočíselný typ bez znaménka. Obsahuje alespoň rozsah [0, 65 535]. | 16 |
%u
|
long long int signed long signed long int
|
Celočíselný typ s dlouhým znaménkem. Může obsahovat alespoň rozsah [−2,147,483,647, +2,147,483,647]. | 32 |
%li nebo %ld
|
unsigned long unsigned long int
|
Dlouhý celočíselný typ bez znaménka. Schopné obsahovat alespoň [0, 4 294 967 295] rozmezí. | 32 |
%lu
|
long long long long int signed long long signed long long int
|
Dlouhý dlouhý celočíselný typ se znaménkem. Schopné obsahovat alespoň rozsah [−9,223,372,036,854,775,807, +9,223,372,036,854,775,807]. Určeno od verze C99 standardu. | 64 |
%lli nebo %lld
|
unsigned long long unsigned long long int
|
Dlouhý dlouhý celočíselný typ bez znaménka. Obsahuje alespoň rozsah [0, +18,446,744,073,709,551,615]. Určeno od verze C99 standardu. | 64 |
%llu
|
float |
Skutečný typ s plovoucí desetinnou čárkou, obvykle označovaný jako typ s plovoucí desetinnou čárkou s jednoduchou přesností. Nespecifikované skutečné vlastnosti (kromě minimálních limitů); ve většině systémů se však jedná o binární formát s plovoucí desetinnou čárkou s jednoduchou přesností IEEE 754 (32 bitů). Tento formát je vyžadován volitelnou přílohou F „Aritmetika s pohyblivou řádovou čárkou IEC 60559“. | Převod z textu: | |
double |
Skutečný typ s plovoucí desetinnou čárkou, obvykle označovaný jako typ s plovoucí desetinnou čárkou s dvojitou přesností. Nespecifikované skutečné vlastnosti (kromě minimálních limitů); ve většině systémů se však jedná o binární formát s plovoucí desetinnou čárkou s dvojitou přesností IEEE 754 (64 bitů). Tento formát je vyžadován volitelnou přílohou F „Aritmetika s pohyblivou řádovou čárkou IEC 60559“. | ||
long double |
Skutečný typ s plovoucí desetinnou čárkou, obvykle mapovaný na rozšířený přesný formát čísel s plovoucí desetinnou čárkou. Skutečné vlastnosti nespecifikovány. Může to být buď formát x86 s plovoucí desetinnou čárkou s prodlouženou přesností (80 bitů, ale typicky 96 bitů nebo 128 bitů v paměti s výplňovými bajty ), non-IEEE „ double-double “ (128 bitů), IEEE 754 čtyřnásobná přesnost s plovoucí desetinnou čárkou -bodový formát (128 bitů), nebo stejný jako dvojitý. Podrobnosti najdete v článku o long double . |
%Lf %LF %Lg %LG %Le %LE %La %LA
|
Skutečná velikost celočíselných typů se liší podle implementace. Standard vyžaduje pouze vztahy velikosti mezi datovými typy a minimálními velikostmi pro každý datový typ:
Požadavky relace jsou, že long long
není menší než long
, což není menší než int
, které není menší než short
. Protože char
velikost je vždy minimální podporovaný datový typ, žádné jiné datové typy (kromě bitových polí ) nemohou být menší.
Minimální velikost pro char
je 8 bitů, minimální velikost pro short
a int
je 16 bitů, long
protože je 32 bitů a long long
musí obsahovat alespoň 64 bitů.
Typ int
by měl být celočíselný typ, se kterým cílový procesor pracuje nejefektivněji. To umožňuje velkou flexibilitu: například všechny typy mohou být 64bitové. Oblíbených je však několik různých schémat šířky celých čísel (datové modely). Protože datový model definuje, jak různé programy komunikují, je v rámci daného aplikačního rozhraní operačního systému použit jednotný datový model.
V praxi char
má obvykle velikost 8 bitů a velikost short
obvykle 16 bitů (stejně jako jejich nepodepsané protějšky). To platí pro platformy tak rozmanité jako devadesátá léta SunOS 4 Unix, Microsoft MS-DOS , moderní Linux a Microchip MCC18 pro vestavěné 8bitové mikrokontroléry PIC . POSIX vyžaduje char
velikost přesně 8 bitů.
Díky různým pravidlům ve standardu C unsigned char
je základní typ používaný pro pole vhodný k ukládání libovolných objektů jiných než bitových polí: nedostatek padding bitů a pasti, definice reprezentace objektu a možnost aliasingu.
Skutečná velikost a chování typů s plovoucí desetinnou čárkou se také liší podle implementace. Jedinou zárukou je, že long double
není menší než double
, což není menší než float
. Obvykle se používají 32bitové a 64bitové binární formáty s plovoucí desetinnou čárkou IEEE 754 .
Standard C99 obsahuje nové skutečné typy s plovoucí desetinnou čárkou float_t
a double_t
definované v <math.h>
. Odpovídají typům používaným pro průběžné výsledky výrazů s plovoucí desetinnou čárkou, když FLT_EVAL_METHOD
je 0, 1 nebo 2. Tyto typy mohou být širší než long double
.
C99 také přidal komplexní typy: float _Complex
, double _Complex
, long double _Complex
.
Booleovský typ
C99 přidal booleovský (true/false) typ _Bool
. Navíc <stdbool.h>
záhlaví definuje bool
jako vhodný alias pro tento typ a také poskytuje makra pro true
a false
. _Bool
funguje podobně jako normální celočíselný typ, s jedinou výjimkou: všechna přiřazení k a, _Bool
která nejsou 0 (false), jsou uložena jako 1 (true). Toto chování existuje, aby se zabránilo přetečení celých čísel při implicitních zužujících konverzích. Například v následujícím kódu:
unsigned char b = 256;
if (b) {
/* do something */
}
Proměnná se b
vyhodnotí jako false, pokud unsigned char
má velikost 8 bitů. Důvodem je, že hodnota 256 nezapadá do datového typu, což má za následek použití nižších 8 bitů, což má za následek nulovou hodnotu. Změna typu však způsobí, že se předchozí kód bude chovat normálně:
_Bool b = 256;
if (b) {
/* do something */
}
Typ _Bool také zajišťuje, že skutečné hodnoty se vždy navzájem porovnají:
_Bool a = 1, b = 2;
if (a == b) {
/* do something */
}
Typy rozdílů velikosti a ukazatele
Specifikace Jazyk C zahrnuje definice typu s size_t
a ptrdiff_t
reprezentovat veličin souvisejících s pamětí. Jejich velikost je definována podle aritmetických schopností cílového procesoru, nikoli podle schopností paměti, jako je dostupný adresní prostor. Oba tyto typy jsou definovány v <stddef.h>
záhlaví ( cstddef
v C ++).
size_t
je celočíselný typ bez znaménka používaný k vyjádření velikosti jakéhokoli objektu (včetně polí) v konkrétní implementaci. Operátor sizeof poskytuje hodnotu typu size_t
. Maximální velikost size_t
je poskytována prostřednictvím SIZE_MAX
makro konstanty, která je definována v záhlaví ( záhlaví v C ++). je zaručeno, že bude široký alespoň 16 bitů. POSIX navíc obsahuje typ celočíselného znaménka se stejnou šířkou jako .
<stdint.h>
cstdint
size_t
ssize_t
size_t
ptrdiff_t
je celočíselný typ se znaménkem používaný k vyjádření rozdílu mezi ukazateli. Je zaručeno, že bude platit pouze proti ukazatelům stejného typu; odčítání ukazatelů sestávajících z různých typů je definováno implementací.
Rozhraní k vlastnostem základních typů
Informace o skutečných vlastnostech, jako je velikost, základních aritmetických typů, jsou poskytovány prostřednictvím konstant makra ve dvou záhlavích: <limits.h>
záhlaví ( climits
záhlaví v C ++) definuje makra pro celočíselné typy a <float.h>
záhlaví ( cfloat
záhlaví v C ++) definuje makra pro typy s plovoucí desetinnou čárkou . Skutečné hodnoty závisí na implementaci.
Vlastnosti celočíselných typů
-
CHAR_BIT
- velikost typu char v bitech (alespoň 8 bitů) -
SCHAR_MIN
,SHRT_MIN
,INT_MIN
,LONG_MIN
,LLONG_MIN
(C99) - minimální možná hodnota podepsaných typy celočíselných: podepsané char podepsané krátké, podepsané int podepsané dlouhé, podepsal long -
SCHAR_MAX
,SHRT_MAX
,INT_MAX
,LONG_MAX
,LLONG_MAX
(C99), - maximální možná hodnota podepsaných celočíselné typy: podepsané char podepsané krátký, podepsané int podepsané dlouho, podepsané long -
UCHAR_MAX
,USHRT_MAX
,UINT_MAX
,ULONG_MAX
,ULLONG_MAX
(C99), - maximální možná hodnota bez znaménka typů celé číslo bez znaménka: char, krátkého čísla bez znaménka, bez znaménka int, unsigned long, unsigned long -
CHAR_MIN
- minimální možná hodnota char -
CHAR_MAX
- maximální možná hodnota char -
MB_LEN_MAX
- maximální počet bajtů ve vícebajtovém znaku
Vlastnosti typů s plovoucí desetinnou čárkou
-
FLT_MIN
,DBL_MIN
,LDBL_MIN
- minimální normalizována kladné hodnoty float, double, dlouho double resp -
FLT_TRUE_MIN
,DBL_TRUE_MIN
,LDBL_TRUE_MIN
(C11) - minimální kladná hodnota float, double, dlouho double resp -
FLT_MAX
,DBL_MAX
,LDBL_MAX
- maximální konečná hodnota float, double, dlouhý dvojitý, resp -
FLT_ROUNDS
-režim zaokrouhlování pro operace s plovoucí desetinnou čárkou -
FLT_EVAL_METHOD
(C99)-metoda vyhodnocení výrazů zahrnujících různé typy s plovoucí desetinnou čárkou -
FLT_RADIX
-radix exponentu v typech s plovoucí desetinnou čárkou -
FLT_DIG
,DBL_DIG
,LDBL_DIG
- počet desetinných míst, které mohou být reprezentovány bez ztráty přesnosti pomocí plováku, dvojitý, dlouhý dvojitý, resp -
FLT_EPSILON
,DBL_EPSILON
,LDBL_EPSILON
- rozdíl mezi 1,0 a další reprezentovatelný hodnoty plováku, dvojitý, dlouhý dvojitý, resp -
FLT_MANT_DIG
,DBL_MANT_DIG
,LDBL_MANT_DIG
- početFLT_RADIX
bázového číslic v plovoucí desetinnou čárkou mantisy pro typy float, double, dlouhý dvojitý, resp -
FLT_MIN_EXP
,DBL_MIN_EXP
,LDBL_MIN_EXP
- minimální záporné celé číslo takové, žeFLT_RADIX
mocniny jeden menší než je počet je normalizovaný float, double, dlouhý dvojitý, resp -
FLT_MIN_10_EXP
,DBL_MIN_10_EXP
,LDBL_MIN_10_EXP
- minimální negativní celé číslo takové, že 10 zvýší na této síle je normalizovaná float, double, dlouhý dvojitý, resp -
FLT_MAX_EXP
,DBL_MAX_EXP
,LDBL_MAX_EXP
- maximální kladné celé číslo takové, žeFLT_RADIX
mocniny jeden menší než je počet je normalizovaný float, double, dlouhý dvojitý, resp -
FLT_MAX_10_EXP
,DBL_MAX_10_EXP
,LDBL_MAX_10_EXP
- maximální kladné celé číslo, jako že 10 zvýší na této síle je normalizovaná float, double, dlouhý dvojitý, resp -
DECIMAL_DIG
(C99)-minimální počet desetinných číslic tak, aby jakýkoli počet nejširších podporovaných typů s plovoucí desetinnou čárkou mohl být reprezentován v desítkové soustavě s přesnostíDECIMAL_DIG
číslic a přečten zpět v původním typu s plovoucí desetinnou čárkou, aniž by došlo ke změně její hodnoty.DECIMAL_DIG
je minimálně 10.
Celočíselné typy s pevnou šířkou
Standard C99 obsahuje definice několika nových typů celých čísel pro zlepšení přenositelnosti programů. Již dostupné základní celočíselné typy byly považovány za nedostatečné, protože jejich skutečné velikosti jsou definovány implementací a mohou se v různých systémech lišit. Nové typy jsou užitečné zejména ve vestavěných prostředích, kde hardware obvykle podporuje pouze několik typů a jejichž podpora se v různých prostředích liší. Všechny nové typy jsou definovány v <inttypes.h>
záhlaví ( cinttypes
záhlaví v C ++) a jsou také k dispozici v <stdint.h>
záhlaví ( cstdint
záhlaví v C ++). Typy lze seskupit do následujících kategorií:
- Přesné šířky celočíselné typy, u kterých je zaručeno, že budou mít stejný počet n bitů napříč všemi implementacemi. Zahrnuto pouze v případě, že je k dispozici v implementaci.
- Celé typy nejmenší šířky, u nichž je zaručeno, že jsou nejmenším typem dostupným v implementaci, který má alespoň zadaný počet n bitů. Zaručeně bude specifikován minimálně pro N = 8,16,32,64.
- Nejrychlejší celočíselné typy, u nichž je zaručeno, že budou nejrychlejším celočíselným typem dostupným v implementaci, který má alespoň zadaný počet n bitů. Zaručeně bude specifikován minimálně pro N = 8,16,32,64.
- Celé typy ukazatelů, u nichž je zaručeno, že budou schopné pojmout ukazatel. Zahrnuto pouze v případě, že je k dispozici v implementaci.
- Celočíselné typy maximální šířky, u nichž je zaručeno, že budou největším celočíselným typem v implementaci.
Následující tabulka shrnuje typy a rozhraní pro získání podrobností implementace ( n odkazuje na počet bitů):
Typová kategorie | Podepsané typy | Nepodepsané typy | ||||
---|---|---|---|---|---|---|
Typ | Minimální hodnota | Maximální hodnota | Typ | Minimální hodnota | Maximální hodnota | |
Přesná šířka | intn_t |
INTn_MIN |
INTn_MAX
|
uintn_t |
0 |
UINTn_MAX
|
Nejmenší šířka | int_leastn_t |
INT_LEASTn_MIN |
INT_LEASTn_MAX
|
uint_leastn_t |
0 |
UINT_LEASTn_MAX
|
Nejrychlejší | int_fastn_t |
INT_FASTn_MIN |
INT_FASTn_MAX
|
uint_fastn_t |
0 |
UINT_FASTn_MAX
|
Ukazatel | intptr_t |
INTPTR_MIN |
INTPTR_MAX
|
uintptr_t |
0 |
UINTPTR_MAX
|
Maximální šířka | intmax_t |
INTMAX_MIN |
INTMAX_MAX
|
uintmax_t |
0 |
UINTMAX_MAX
|
Specifikátory formátu Printf a Scanf
<inttypes.h>
Záhlaví ( cinttypes
v C ++) poskytuje funkce, které zvyšují funkčnost typů definovaných v <stdint.h>
záhlaví. Definuje makra pro formátovací řetězec formátu printf a specifikátor řetězce formátu scanf odpovídající typům definovaným v <stdint.h>
a několika funkcím pro práci s typy intmax_t
a uintmax_t
. Tato hlavička byla přidána do C99 .
- Řetězec formátu Printf
Makra jsou ve formátu . Zde {fmt} definuje výstupní formátování a je jedním z (desítkových), (šestnáctkových), (osmičkových), (bez znaménka) a (celého čísla). {typ} definuje typ argumentu, a je jedním z , , , , , kde odpovídá počtu bitů v argumentu.
PRI{fmt}{type}
d
x
o
u
i
n
FASTn
LEASTn
PTR
MAX
n
- Řetězec formátu Scanf
Makra jsou ve formátu . Zde {fmt} definuje výstupní formátování a je jedním z (desítkových), (šestnáctkových), (osmičkových), (bez znaménka) a (celého čísla). {typ} definuje typ argumentu, a je jedním z , , , , , kde odpovídá počtu bitů v argumentu.
SCN{fmt}{type}
d
x
o
u
i
n
FASTn
LEASTn
PTR
MAX
n
- Funkce
Další typy s plovoucí desetinnou čárkou
Podobně jako u celočíselných typů s pevnou šířkou specifikuje ISO/IEC TS 18661 typy s plovoucí desetinnou čárkou pro výměnu IEEE 754 a rozšířené formáty v binárních a desítkových soustavách:
-
_FloatN
pro formáty binární výměny; -
_DecimalN
pro formáty desítkové výměny; -
_FloatNx
pro binární rozšířené formáty; -
_DecimalNx
pro desetinné rozšířené formáty.
Struktury
Struktury agregují úložiště více datových položek potenciálně odlišných datových typů do jednoho paměťového bloku, na který odkazuje jedna proměnná. Následující příklad deklaruje datový typ, struct birthday
který obsahuje jméno a datum narození osoby. Za definicí struktury následuje deklarace proměnné, John
která přiděluje potřebné úložiště.
struct birthday {
char name[20];
int day;
int month;
int year;
};
struct birthday John;
Rozložení paměti struktury je problém jazykové implementace pro každou platformu, s několika omezeními. Adresa paměti prvního člena musí být stejná jako adresa samotné struktury. Struktury lze inicializovat nebo jim přiřadit přiřazené složené literály. Funkce může přímo vrátit strukturu, i když to často není za běhu efektivní. Od C99 může struktura také končit flexibilním členem pole .
Struktura obsahující ukazatel na strukturu vlastního typu se běžně používá k vytváření propojených datových struktur :
struct node {
int val;
struct node *next;
};
Pole
Pro každý typ T
, kromě neplatných a funkčních typů, existují typy „pole N
prvků typu T
“ . Pole je kolekce hodnot stejného typu uložených souvisle v paměti. Pole velikosti N
je indexováno celými čísly od 0
až do včetně N−1
. Zde je krátký příklad:
int cat[10]; // array of 10 elements, each of type int
Pole lze inicializovat pomocí složeného inicializátoru, ale nelze je přiřadit. Pole se předávají do funkcí předáním ukazatele na první prvek. Vícerozměrná pole jsou definována jako „pole pole…“ a všechna kromě nejvzdálenější dimenze musí mít velikost časově konstantní kompilace:
int a[10][8]; // array of 10 elements, each of type 'array of 8 int elements'
Ukazatele
Každý datový typ T
má odpovídající ukazatelT
typu na . Ukazatel je datový typ, který obsahuje adresu paměťového místa proměnné určitého typu. Jsou deklarovány deklarátorem *
typu asterisk ( ) podle základního typu úložiště a před názvem proměnné. Mezery před nebo za hvězdičkou jsou volitelné.
char *square;
long *circle;
int *oval;
Ukazatele mohou být také deklarovány pro datové typy ukazatelů, čímž se vytvoří více nepřímých ukazatelů, například char ** a int *** , včetně ukazatelů na typy polí. Ty jsou méně časté než řada ukazatelů a jejich syntaxe může být matoucí:
char *pc[10]; // array of 10 elements of 'pointer to char'
char (*pa)[10]; // pointer to a 10-element array of char
Prvek pc
vyžaduje deset bloků paměti o velikosti ukazatele nachar
(obvykle 40 nebo 80 bajtů na běžných platformách), ale prvek pa
je pouze jeden ukazatel (velikost 4 nebo 8 bajtů) a data, na která odkazuje, je pole deseti bajtů ( ).
sizeof *pa == 10
Odbory
Typ union je speciální konstrukce, která umožňuje přístup ke stejným paměťového bloku pomocí volby rozdílných popisů typu. Například může být deklarováno sjednocení datových typů, které umožní čtení stejných dat buď jako celé číslo, plovák nebo jakýkoli jiný typ deklarovaný uživatelem:
union {
int i;
float f;
struct {
unsigned int u;
double d;
} s;
} u;
Celková velikost u
je velikost u.s
- což je součet velikostí u.s.u
a u.s.d
- protože s
je větší než oba i
a f
. Při přiřazování něčeho mohou být u.i
některé části u.f
zachovány, pokud u.i
je menší než u.f
.
Čtení od člena odboru není totéž jako přetypování, protože hodnota člena není převedena, ale pouze přečtena.
Ukazatele funkcí
Ukazatele funkcí umožňují odkazovat na funkce s konkrétním podpisem. Chcete -li například uložit adresu standardní funkce abs
do proměnné my_int_f
:
int (*my_int_f)(int) = &abs;
// the & operator can be omitted, but makes clear that the "address of" abs is used here
Ukazatele funkcí jsou vyvolávány jménem stejně jako normální volání funkcí. Ukazatele funkcí jsou oddělené od ukazatelů a ukazatelů neplatnosti .
Kvalifikátory typu
Výše uvedené typy lze dále charakterizovat kvalifikátory typů , čímž se získá kvalifikovaný typ . Od roku 2014 a C11 existují ve standardu C čtyři kvalifikátory typu: const
( C89 ), volatile
( C89 ), restrict
( C99 ) a _Atomic
( C11 ) - druhý jmenovaný má soukromé jméno, aby se zabránilo střetu s uživatelskými jmény, ale běžnější název atomic
může použít, pokud <stdatomic.h>
je zahrnuto záhlaví. Z nich const
je zdaleka nejznámější a nejpoužívanější, objevuje se ve standardní knihovně a vyskytuje se při jakémkoli významném používání jazyka C, který musí splňovat konstantní správnost . Ostatní kvalifikátory se používají pro programování na nízké úrovni, a přestože jsou široce používány, jsou typickými programátory používány jen zřídka.