Datové typy C - C data types

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 %hhipro numerický výstup)
unsigned char Stejné velikosti jako char , ale zaručeně bez znaménka. Obsahuje alespoň rozsah [0, 255]. 8 %c (nebo %hhupro 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 longnení menší než long, což není menší než int, které není menší než short. Protože charvelikost je vždy minimální podporovaný datový typ, žádné jiné datové typy (kromě bitových polí ) nemohou být menší.

Minimální velikost pro charje 8 bitů, minimální velikost pro shorta intje 16 bitů, longprotože je 32 bitů a long longmusí obsahovat alespoň 64 bitů.

Typ intby 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 charmá obvykle velikost 8 bitů a velikost shortobvykle 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 charvelikost přesně 8 bitů.

Díky různým pravidlům ve standardu C unsigned charje 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 doublenení 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_ta double_tdefinované 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_METHODje 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 booljako vhodný alias pro tento typ a také poskytuje makra pro truea false. _Boolfunguje podobně jako normální celočíselný typ, s jedinou výjimkou: všechna přiřazení k a, _Boolkterá 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 bvyhodnotí jako false, pokud unsigned charmá 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_ta ptrdiff_treprezentovat 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í ( cstddefv C ++).

size_tje 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_tje poskytována prostřednictvím SIZE_MAXmakro 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>cstdintsize_tssize_tsize_t

ptrdiff_tje 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í ( climitszáhlaví v C ++) definuje makra pro celočíselné typy a <float.h>záhlaví ( cfloatzá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čet FLT_RADIXbá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é, že FLT_RADIXmocniny 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é, že FLT_RADIXmocniny 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_DIGje 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í ( cinttypeszáhlaví v C ++) a jsou také k dispozici v <stdint.h>záhlaví ( cstdintzá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í ( cinttypesv 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_ta 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}dxouinFASTnLEASTnPTRMAXn

Ř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}dxouinFASTnLEASTnPTRMAXn

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 birthdaykterý obsahuje jméno a datum narození osoby. Za definicí struktury následuje deklarace proměnné, Johnkterá 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 Nprvků typu T . Pole je kolekce hodnot stejného typu uložených souvisle v paměti. Pole velikosti Nje indexováno celými čísly od 0až 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 Tmá 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 pcvyžaduje deset bloků paměti o velikosti ukazatele nachar (obvykle 40 nebo 80 bajtů na běžných platformách), ale prvek paje 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 uje velikost u.s- což je součet velikostí u.s.ua u.s.d- protože sje větší než oba ia f. Při přiřazování něčeho mohou být u.iněkteré části u.fzachovány, pokud u.ije 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 absdo 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 atomicmůže použít, pokud <stdatomic.h>je zahrnuto záhlaví. Z nich constje 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.

Viz také

Reference