Tipuri de date C - C data types
| Biblioteca standard C |
|---|
| Subiecte generale |
| Anteturi diverse |
În limbajul de programare C , tipurile de date constituie semantica și caracteristicile stocării elementelor de date. Acestea sunt exprimate în sintaxa limbii sub formă de declarații pentru locațiile de memorie sau variabile . Tipurile de date determină, de asemenea, tipurile de operații sau metodele de prelucrare a elementelor de date.
Limbajul C oferă tipuri de bază aritmetice, cum ar fi tipuri de numere întregi și numere reale , și sintaxă pentru a construi tipuri de matrice și compuse. Anteturile pentru biblioteca standard C , care urmează să fie utilizate prin intermediul directivelor , conțin definiții ale tipurilor de suport, care au proprietăți suplimentare, cum ar fi furnizarea de stocare cu o dimensiune exactă, independent de implementarea limbajului pe platforme hardware specifice.
Tipuri de bază
Principalele tipuri
Limbajul C oferă cele patru specificații de bază aritmetice de tip char , int , float și double , iar modificatorii semnați , nesemnați , scurți și lungi . Următorul tabel listează combinațiile permise în specificarea unui set mare de declarații specifice dimensiunii stocării.
| Tip | Explicaţie | Dimensiune minimă (biți) | Specificator de format |
|---|---|---|---|
char |
Cea mai mică unitate adresabilă a mașinii care poate conține un set de caractere de bază. Este un tip întreg . Tipul real poate fi semnat sau nesemnat. Conține biți CHAR_BIT. | 8 |
%c
|
signed char |
De aceeași dimensiune ca și char , dar garantat că va fi semnat. Capabil să conțină cel puțin intervalul [-127, +127]. | 8 |
%c (sau %hhipentru ieșire numerică)
|
unsigned char |
De aceeași dimensiune ca și char , dar garantat că este nesemnat. Conține cel puțin intervalul [0, 255]. | 8 |
%c (sau %hhupentru ieșire numerică)
|
shortshort intsigned shortsigned short int
|
Tip întreg semnat scurt . Capabil să conțină cel puțin intervalul [-32.767, +32.767]. | 16 |
%hi sau %hd
|
unsigned shortunsigned short int
|
Tip întreg nesemnat scurt . Conține cel puțin intervalul [0, 65.535]. | 16 |
%hu
|
intsignedsigned int
|
Tip întreg de bază semnat. Capabil să conțină cel puțin intervalul [-32.767, +32.767]. | 16 |
%i sau %d
|
unsignedunsigned int
|
Tipul de bază întreg nesemnat. Conține cel puțin intervalul [0, 65.535]. | 16 |
%u
|
longlong intsigned longsigned long int
|
Tip întreg semnat lung . Capabil să conțină cel puțin intervalul [-2.147.483.647, +2.147.483.647]. | 32 |
%li sau %ld
|
unsigned longunsigned long int
|
Tip întreg nesemnat lung . Capabil să conțină cel puțin intervalul [0, 4.294.967.295]. | 32 |
%lu
|
long longlong long intsigned long longsigned long long int
|
Tip întreg semnat lung lung . Capabil să conțină cel puțin intervalul [-9.223.372.036.854.775.807, +9.223.372.036.854.775.807]. Specificat de la versiunea C99 a standardului. | 64 |
%lli sau %lld
|
unsigned long longunsigned long long int
|
Tip întreg lung nesemnat. Conține cel puțin intervalul [0, +18.446.744.073.709.551.615]. Specificat de la versiunea C99 a standardului. | 64 |
%llu
|
float |
Tipul cu virgulă mobilă reală, denumit de obicei un tip cu virgulă mobilă de o singură precizie. Proprietăți reale nespecificate (cu excepția limitelor minime); cu toate acestea, pe majoritatea sistemelor, acesta este formatul IEEE 754 cu virgulă mobilă cu precizie simplă (32 biți). Acest format este cerut de anexa F opțională "IEC 60559 aritmetică în virgulă mobilă". | Conversia din text: | |
double |
Tipul cu virgulă mobilă reală, denumit de obicei un tip cu virgulă mobilă de dublă precizie. Proprietăți reale nespecificate (cu excepția limitelor minime); cu toate acestea, pe majoritatea sistemelor, acesta este formatul IEEE 754 cu virgulă mobilă cu precizie dublă (64 biți). Acest format este cerut de anexa F opțională "IEC 60559 aritmetică în virgulă mobilă". | ||
long double |
Tip real cu virgulă mobilă, de obicei mapat la un format numeric cu virgulă mobilă de precizie extinsă . Proprietăți reale nespecificate. Poate fi format în virgulă mobilă cu precizie extinsă x86 (80 de biți, dar de obicei 96 de biți sau 128 de biți în memorie cu octeți de umplere ), non-IEEE „ dublu-dublu ” (128 biți), IEEE 754 flotant cu precizie cvadruplă -format punct (128 biți), sau la fel ca dublu. Consultați articolul despre dubla lungă pentru detalii. |
%Lf %LF%Lg %LG%Le %LE%La %LA
|
Mărimea reală a tipurilor de numere întregi variază în funcție de implementare. Standardul necesită doar relații de dimensiune între tipurile de date și dimensiunile minime pentru fiecare tip de date:
Cerințele de relație sunt că long longnu este mai mic decât long, care nu este mai mic decât int, care nu este mai mic decât short. Deoarece chardimensiunea este întotdeauna tipul minim de date acceptate, niciun alt tip de date (cu excepția câmpurilor de biți ) nu poate fi mai mic.
Dimensiunea minimă pentru chareste de 8 biți, dimensiunea minimă pentru shortși inteste de 16 biți, longdeoarece este de 32 de biți și long longtrebuie să conțină cel puțin 64 de biți.
Tipul inttrebuie să fie tipul întreg cu care procesorul țintă lucrează cel mai eficient. Acest lucru permite o mare flexibilitate: de exemplu, toate tipurile pot fi pe 64 de biți. Cu toate acestea, sunt cunoscute mai multe scheme de lățime întregi diferite (modele de date). Deoarece modelul de date definește modul în care comunică diferite programe, se utilizează un model de date uniform într-o anumită interfață de aplicație a sistemului de operare.
În practică, charare de obicei o dimensiune de 8 biți și shortare de obicei o dimensiune de 16 biți (la fel ca și omologii lor nesemnați). Acest lucru este valabil pentru platforme la fel de diverse precum SunOS 4 Unix din anii 90 , Microsoft MS-DOS , Linux modern și Microchip MCC18 pentru microcontrolere PIC încorporate pe 8 biți . POSIX necesită o chardimensiune de exact 8 biți.
Diferite reguli din standardul C fac unsigned charca tipul de bază utilizat pentru matrici să fie adecvat pentru stocarea obiectelor arbitrare fără câmp de biți: lipsa de biți de umplere și reprezentări trap, definiția reprezentării obiectelor și posibilitatea aliasării.
Mărimea reală și comportamentul tipurilor cu virgulă mobilă variază, de asemenea, în funcție de implementare. Singura garanție este că long doublenu este mai mic decât double, care nu este mai mic decât float. De obicei, sunt utilizate formatele pe virgulă mobilă IEEE 754 pe 32 și 64 de biți .
Standardul C99 include noi tipuri reale în virgulă mobilă float_tși double_t, definit în <math.h>. Ele corespund tipurilor utilizate pentru rezultatele intermediare ale expresiilor în virgulă mobilă atunci când FLT_EVAL_METHODeste 0, 1 sau 2. Aceste tipuri pot fi mai largi decât long double.
C99 a adăugat , de asemenea , complexe tipuri: float _Complex, double _Complex, long double _Complex.
Tipul boolean
C99 a adăugat un tip boolean (adevărat / fals) _Bool. În plus, <stdbool.h>antetul se definește boolca un alias convenabil pentru acest tip și oferă, de asemenea, macrocomenzi pentru trueși false. _Boolfuncționează similar cu un tip întreg normal, cu o singură excepție: orice alocări către un _Boolcare nu sunt 0 (fals) sunt stocate ca 1 (adevărat). Acest comportament există pentru a evita depășirile întregi în conversiile de îngustare implicită. De exemplu, în următorul cod:
unsigned char b = 256;
if (b) {
/* do something */
}
Variabila se bevaluează la fals dacă unsigned charare o dimensiune de 8 biți. Acest lucru se datorează faptului că valoarea 256 nu se încadrează în tipul de date, ceea ce duce la utilizarea celor 8 biți inferiori ai acestuia, rezultând o valoare zero. Cu toate acestea, modificarea tipului face ca codul anterior să se comporte normal:
_Bool b = 256;
if (b) {
/* do something */
}
Tipul _Bool asigură, de asemenea, că valorile adevărate se compară întotdeauna egale între ele:
_Bool a = 1, b = 2;
if (a == b) {
/* do something */
}
Dimensiune și tipuri de diferențe ale indicatorului
Specificația limbajul C include typedef s size_tși ptrdiff_tpentru reprezentarea cantităților-memorie aferente. Dimensiunea lor este definită în funcție de capacitățile aritmetice ale procesorului țintă, nu de capacitățile de memorie, cum ar fi spațiul de adresă disponibil. Ambele tipuri sunt definite în <stddef.h>antet ( cstddefîn C ++).
size_teste un tip întreg nesemnat folosit pentru a reprezenta dimensiunea oricărui obiect (inclusiv matrici) în implementarea particulară. Operatorul sizeof produce o valoare de tip size_t. Dimensiunea maximă a size_teste furnizată prin SIZE_MAX, o constantă macro care este definită în antet ( antet în C ++). este garantat să aibă o lățime de cel puțin 16 biți. In plus, POSIX include , care este un tip întreg semnat de aceeași lățime ca și .
<stdint.h>cstdintsize_tssize_tsize_t
ptrdiff_teste un tip întreg semnat utilizat pentru a reprezenta diferența dintre pointeri. Se garantează că este valabil numai împotriva pointerilor de același tip; scăderea pointerilor constând din diferite tipuri este definită de implementare.
Interfață cu proprietățile tipurilor de bază
Informațiile despre proprietățile reale, cum ar fi dimensiunea, tipurilor de bază aritmetice, sunt furnizate prin constante macro în două antete: <limits.h>antetul ( climitsantetul în C ++) definește macro-urile pentru tipurile întregi și <float.h>antetul ( cfloatantetul în C ++) definește macrocomenzile pentru tipurile cu virgulă mobilă . Valorile reale depind de implementare.
Proprietățile tipurilor întregi
-
CHAR_BIT- dimensiunea tipului de caractere în biți (cel puțin 8 biți) -
SCHAR_MIN,SHRT_MIN,INT_MIN,LONG_MIN,LLONG_MIN(C99) - valoarea minimă posibilă a tipurilor semnate intregi: char semnat, semnat scurt, int semnat, semnat lung, semnat lung lung -
SCHAR_MAX,SHRT_MAX,INT_MAX,LONG_MAX,LLONG_MAX(C99) - valoarea maximă posibilă a tipurilor semnate intregi: char semnat, semnat scurt, int semnat, semnat lung, semnat lung lung -
UCHAR_MAX,USHRT_MAX,UINT_MAX,ULONG_MAX,ULLONG_MAX(C99) - valoarea maximă posibilă a tipurilor unsigned intregi: unsigned char, scurt, unsigned unsigned int, unsigned long, unsigned lung lung -
CHAR_MIN- valoarea minimă posibilă a caracterului -
CHAR_MAX- valoarea maximă posibilă a caracterului -
MB_LEN_MAX- numărul maxim de octeți într-un caracter multibyte
Proprietățile tipurilor de virgulă mobilă
-
FLT_MIN,DBL_MIN,LDBL_MIN- minim normalizat valoare pozitivă de float, dublu, lung dublu respectiv -
FLT_TRUE_MIN,DBL_TRUE_MIN,LDBL_TRUE_MIN(C11) - valoarea minimă pozitivă float, dublu, lung dublu respectiv -
FLT_MAX,DBL_MAX,LDBL_MAX- valoarea maximă finită de float, dublu, lung dublu, respectiv -
FLT_ROUNDS- modul de rotunjire pentru operații în virgulă mobilă -
FLT_EVAL_METHOD(C99) - metodă de evaluare a expresiilor care implică diferite tipuri în virgulă mobilă -
FLT_RADIX- raza exponentului în tipurile cu virgulă mobilă -
FLT_DIG,DBL_DIG,LDBL_DIG- numărul de cifre zecimale , care pot fi reprezentate fără a pierde din precizie de float, dublu, lung dublu, respectiv -
FLT_EPSILON,DBL_EPSILON,LDBL_EPSILON- diferența între 1.0 și următoarea valoare reprezentabile de float, dublu, lung dublu, respectiv -
FLT_MANT_DIG,DBL_MANT_DIG,LDBL_MANT_DIG- numărul deFLT_RADIXcifre -base în virgulă flotantă significand pentru tipurile float, dublu, lung dublu, respectiv -
FLT_MIN_EXP,DBL_MIN_EXP,LDBL_MIN_EXP- negativ minim întreg astfel încâtFLT_RADIXridicat la o singură putere mai mică decât numărul respectiv este un float normalizat, dublu, lung dublu, respectiv -
FLT_MIN_10_EXP,DBL_MIN_10_EXP,LDBL_MIN_10_EXP- negativ minim întreg , astfel încât 10 ridicat la acea putere este un float normalizat, dublu, lung dublu, respectiv -
FLT_MAX_EXP,DBL_MAX_EXP,LDBL_MAX_EXP- pozitiv maxim întreg , astfel încâtFLT_RADIXridicat la o singură putere mai mică decât numărul respectiv este un float normalizat, dublu, lung dublu, respectiv -
FLT_MAX_10_EXP,DBL_MAX_10_EXP,LDBL_MAX_10_EXP- pozitiv maxim întreg , astfel încât 10 ridicat la acea putere este un float normalizat, dublu, lung dublu, respectiv -
DECIMAL_DIG(C99) - numărul minim de cifre zecimale astfel încât orice număr al celui mai larg tip de virgulă mobilă acceptată să poată fi reprezentat în zecimal cu o precizie deDECIMAL_DIGcifre și citit înapoi în tipul virgulă mobilă originală fără a-i modifica valoarea.DECIMAL_DIGeste cel puțin 10.
Tipuri întregi cu lățime fixă
Standardul C99 include definiții ale mai multor noi tipuri întregi pentru a spori portabilitatea programelor. Tipurile întregi de bază deja disponibile au fost considerate insuficiente, deoarece dimensiunile lor reale sunt definite de implementare și pot varia în funcție de sisteme diferite. Noile tipuri sunt utile în special în mediile încorporate în care hardware-ul acceptă de obicei doar mai multe tipuri și care suportă variază între medii diferite. Toate tipurile noi sunt definite în <inttypes.h>antet ( cinttypesantet în C ++) și, de asemenea, sunt disponibile la <stdint.h>antet ( cstdintantet în C ++). Tipurile pot fi grupate în următoarele categorii:
- Tipuri întregi Exact lățime care sunt garantate să aibă același număr n de biți din toate implementările. Inclus numai dacă este disponibil în implementare.
- Tipuri întregi cel lățime care sunt garantate să fie cel mai mic tip disponibil în implementare, care are cel puțin specificat număr n de biți. Garantat pentru a fi specificat pentru cel puțin N = 8,16,32,64.
- Cele mai rapide tipuri întregi , care sunt garantate pentru a fi cel mai rapid tip întreg disponibil în punerea în aplicare, care are cel puțin specificat numărul n de biți. Garantat pentru a fi specificat pentru cel puțin N = 8,16,32,64.
- Tipuri întregi de pointer care sunt garantate pentru a putea ține un pointer. Inclus numai dacă este disponibil în implementare.
- Tipuri întregi cu lățime maximă care sunt garantate a fi cel mai mare tip întreg din implementare.
Următorul tabel rezumă tipurile și interfața pentru a obține detaliile implementării ( n se referă la numărul de biți):
| Categorie tip | Tipuri semnate | Tipuri nesemnate | ||||
|---|---|---|---|---|---|---|
| Tip | Valoare minimă | Valoare maximă | Tip | Valoare minimă | Valoare maximă | |
| Lățime exactă | intn_t |
INTn_MIN |
INTn_MAX
|
uintn_t |
0 |
UINTn_MAX
|
| Lățimea minimă | int_leastn_t |
INT_LEASTn_MIN |
INT_LEASTn_MAX
|
uint_leastn_t |
0 |
UINT_LEASTn_MAX
|
| Cel mai rapid | int_fastn_t |
INT_FASTn_MIN |
INT_FASTn_MAX
|
uint_fastn_t |
0 |
UINT_FASTn_MAX
|
| Pointer | intptr_t |
INTPTR_MIN |
INTPTR_MAX
|
uintptr_t |
0 |
UINTPTR_MAX
|
| Lățimea maximă | intmax_t |
INTMAX_MIN |
INTMAX_MAX
|
uintmax_t |
0 |
UINTMAX_MAX
|
Specificatori de format Printf și scanf
<inttypes.h>Antet ( cinttypesîn C ++) oferă caracteristici care sporesc funcționalitatea tipurilor definite în <stdint.h>antet. Acesta definește macrocomenzi pentru șiruri de format printf și specificatori de șiruri de format scanf corespunzătoare tipurilor definite <stdint.h>și mai multor funcții pentru lucrul cu tipurile intmax_tși uintmax_t. Acest antet a fost adăugat în C99 .
- Șir de format Printf
Macrocomenzile sunt în format . Aici {fmt} definește formatarea de ieșire și este una dintre (zecimal), (hexazecimal), (octal), (nesemnat) și (întreg). {tip} definește tipul de argument și este unul dintre , , , , , unde corespunde numărului de biți în argument.
PRI{fmt}{type}dxouinFASTnLEASTnPTRMAXn
- Șir de format Scanf
Macrocomenzile sunt în format . Aici {fmt} definește formatarea de ieșire și este una dintre (zecimal), (hexazecimal), (octal), (nesemnat) și (întreg). {tip} definește tipul de argument și este unul dintre , , , , , unde corespunde numărului de biți în argument.
SCN{fmt}{type}dxouinFASTnLEASTnPTRMAXn
- Funcții
Tipuri suplimentare în virgulă mobilă
În mod similar cu tipurile întregi cu lățime fixă, ISO / IEC TS 18661 specifică tipurile cu virgulă mobilă pentru schimbul IEEE 754 și formate extinse în binar și zecimal:
-
_FloatNpentru formate de schimb binar; -
_DecimalNpentru formatele de schimb zecimal; -
_FloatNxpentru formate binare extinse; -
_DecimalNxpentru formate extinse zecimale.
Structuri
Structurile agregează stocarea mai multor elemente de date, de tipuri de date potențial diferite, într-un bloc de memorie la care se face referire printr-o singură variabilă. Următorul exemplu declară tipul de date struct birthdaycare conține numele și ziua de naștere a unei persoane. Definiția structurii este urmată de o declarație a variabilei Johncare alocă stocarea necesară.
struct birthday {
char name[20];
int day;
int month;
int year;
};
struct birthday John;
Aspectul memoriei unei structuri este o problemă de implementare a limbajului pentru fiecare platformă, cu câteva restricții. Adresa de memorie a primului membru trebuie să fie aceeași cu adresa structurii în sine. Structurile pot fi inițializate sau atribuite folosirii literelor compuse. O funcție poate returna direct o structură, deși acest lucru nu este adesea eficient în timpul rulării. De la C99 , o structură se poate termina, de asemenea, cu un membru de matrice flexibil .
O structură care conține un pointer către o structură de tip propriu este utilizată în mod obișnuit pentru a construi structuri de date legate :
struct node {
int val;
struct node *next;
};
Matrice
Pentru fiecare tip T, cu excepția tipurilor de funcții și de goluri , există tipurile „matrice de Nelemente de tip T” . O matrice este o colecție de valori, toate de același tip, stocate contigu în memorie. O matrice de dimensiuni Neste indexată de numere întregi de la 0până la inclusiv N−1. Iată un scurt exemplu:
int cat[10]; // array of 10 elements, each of type int
Tablourile pot fi inițializate cu un inițializator compus, dar nu alocate. Tablourile sunt transmise funcțiilor trecând un pointer la primul element. Tablourile multidimensionale sunt definite ca "matrice de matrice ..." și toate, cu excepția dimensiunii exterioare, trebuie să aibă dimensiunea constantă a timpului de compilare:
int a[10][8]; // array of 10 elements, each of type 'array of 8 int elements'
Indicatori
Fiecare tip de date Tare un pointer deT tip corespunzător . Un indicator este un tip de date care conține adresa unei locații de stocare a unei variabile de un anumit tip. Acestea sunt declarate cu declaratorul de tip asterisc ( *) urmând tipul de stocare de bază și precedând numele variabilei. Spațiul alb înainte sau după asterisc este opțional.
char *square;
long *circle;
int *oval;
Pointerii pot fi, de asemenea, declarați pentru tipurile de date ale pointerului, creând astfel mai multe pointeri indirecte, cum ar fi char ** și int *** , inclusiv pointeri către tipuri de matrice. Acestea din urmă sunt mai puțin frecvente decât o serie de indicatori, iar sintaxa lor poate fi confuză:
char *pc[10]; // array of 10 elements of 'pointer to char'
char (*pa)[10]; // pointer to a 10-element array of char
Elementul pcnecesită zece blocuri de memorie de dimensiunea indicatoruluichar (de obicei 40 sau 80 de octeți pe platformele comune), dar elementul paeste doar un indicator (dimensiunea 4 sau 8 octeți), iar datele la care se referă sunt o matrice de zece octeți ( ).
sizeof *pa == 10
Sindicatele
Un tip de uniune este o construcție specială care permite accesul la același bloc de memorie utilizând o gamă de descrieri de tipuri diferite. De exemplu, o uniune de tipuri de date poate fi declarată pentru a permite citirea acelorași date fie ca un număr întreg, ca float sau orice alt tip declarat de utilizator:
union {
int i;
float f;
struct {
unsigned int u;
double d;
} s;
} u;
Dimensiunea totală a ueste mărimea lui u.s- care se întâmplă să fie suma mărimilor lui u.s.uși u.s.d- deoarece seste mai mare decât ambele iși f. Atunci când atribuiți ceva u.i, unele părți din u.fpot fi păstrate dacă u.isunt mai mici decât u.f.
Citirea de la un membru al sindicatului nu este la fel ca castingul, deoarece valoarea membrului nu este convertită, ci doar citită.
Indicații funcționale
Indicatorii de funcții permit referirea funcțiilor cu o anumită semnătură. De exemplu, pentru a stoca adresa funcției standard absîn variabilă 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
Indicatorii de funcție sunt invocați prin nume la fel ca apelurile de funcții normale. Pointerii de funcții sunt separați de pointeri și pointeri de gol .
Tipul calificărilor
Tipurile menționate mai sus pot fi caracterizate în continuare prin calificative de tip , rezultând un tip calificat . Începând cu 2014 și C11 , există patru calificative de tip în standardul C: const( C89 ), volatile( C89 ), restrict( C99 ) și _Atomic( C11 ) - acesta din urmă are un nume privat pentru a evita confruntarea cu numele utilizatorilor, dar numele mai obișnuit atomicpoate să fie utilizat dacă <stdatomic.h>antetul este inclus. Dintre acestea, consteste de departe cea mai cunoscută și cea mai utilizată, care apare în biblioteca standard și întâlnită în orice utilizare semnificativă a limbajului C, care trebuie să satisfacă corectitudinea constanței . Celelalte calificative sunt utilizate pentru programarea la nivel scăzut și, deși sunt utilizate pe scară largă acolo, sunt rareori folosite de programatorii tipici.