Типы данных - info at fenster.name

advertisement
Òèïû äàííûõ
À. Ã. Ôåíñòåð,
fenster@fenster.name
20 ìàðòà 2010 ã.
Íà ýòîì çàíÿòèè ìû ïîãîâîðèì ïðî ðàçëè÷íûå òèïû äàííûõ â ÿçûêå C.
1
Ïðåäñòàâëåíèå ÷èñåë â êîìïüþòåðå
Âñïîìíèì, êàê êîìïüþòåð õðàíèò öåëûå è âåùåñòâåííûå ÷èñëà. Äëÿ
õðàíåíèÿ ÷èñåë èñïîëüçóåòñÿ äâîè÷íàÿ ñèñòåìà. Öåëûå áåççíàêîâûå ÷èñëà õðàíÿòñÿ î÷åâèäíûì îáðàçîì, öåëûå ÷èñëà ñî çíàêîì ïðåäñòàâëåíû
â äîïîëíèòåëüíîì êîäå: áèòîâîå ïðåäñòàâëåíèå ÷èñëà (−k) ñîâïàäàåò ñ
áèòîâûì ïðåäñòàâëåíèåì áåççíàêîâîãî ÷èñëà 2N − k, ãäå N êîëè÷åñòâî
äâîè÷íûõ ðàçðÿäîâ (áèò) â äàííîì òèïå. Òàêîå ïðåäñòàâëåíèå âûáðàíî â îñíîâíîì ïî òîé ïðè÷èíå, ÷òî äîáàâëåíèå îòðèöàòåëüíûõ ÷èñåë íå
èçìåíÿåò àðèôìåòè÷åñêèå îïåðàöèè (â ÷àñòíîñòè, àâòîìàòè÷åñêè âûïîëíÿåòñÿ k + (−k) = 0).
Âåùåñòâåííûå ÷èñëà â êîìïüþòåðå õðàíÿòñÿ â ôîðìàòå ñ ïëàâàþùåé
çàïÿòîé (ïî-àíãëèéñêè oating point, ¾ïëàâàþùàÿ òî÷êà¿, ïîñêîëüêó ó
íèõ ïðèíÿòî èñïîëüçîâàòü äëÿ çàïèñè äðîáåé òî÷êó, à íå çàïÿòóþ). ×èñëî õðàíèòñÿ â âèäå ±s·2e, ãäå s ìàíòèññà (â àíãëèéñêîì ÿçûêå ïðèíÿò
òåðìèí signicand), e ïîðÿäîê (exponent). Ïðåäñòàâëåíèå îáû÷íî íîðìàëèçîâàíî (1 6 s < 2).
Ðàññìîòðèì ñîîòâåòñòâèå òèïîâ ÿçûêà C è ïåðå÷èñëåííûõ ìîäåëåé
ïðåäñòàâëåíèÿ ÷èñåë, à òàêæå ðàçáåð¼ì îñíîâíûå íåäîñòàòêè êàæäîãî
èç ñïîñîáîâ ïðåäñòàâëåíèÿ.
Òèïû äàííûõ
2
Öåëûå ÷èñëà
Ðàçìåð òèïà char 1 áàéò (sizeof(char) == 1). Çàìåòèì, ÷òî ñòàíäàðòû îïðåäåëÿþò áàéò êàê àäðåñóåìûé ýëåìåíò, äîñòàòî÷íûé äëÿ õðàíåíèÿ îäíîãî ñèìâîëà, ñîñòîÿùèé íå ìåíåå ÷åì èç âîñüìè áèò (êîíñòàíòà
CHAR_BIT èç limits.h äà¼ò òî÷íîå çíà÷åíèå äëÿ äàííîé ðåàëèçàöèè).
Ðàçìåðû îñòàëüíûõ òèïîâ ñòàíäàðòàìè â ÿâíîì âèäå íå îïðåäåëÿþòñÿ,
îïðåäåëåíû ëèøü ñîîòíîøåíèÿ ìåæäó íèìè, à limits.h îïðåäåëÿåò ïðåäåëû äëÿ äàííîé ðåàëèçàöèè: INT_MAX, INT_MIN, UINT_MAX è ïðî÷èå.
Ê ñòàíäàðòíûì çíàêîâûì öåëûì òèïàì îòíîñÿòñÿ signed char, short
int, int, long int è long long int. Ê ñòàíäàðòíûì áåççíàêîâûì öåëûì
òèïàì îòíîñÿòñÿ òå æå òèïû ñ äîáàâëåííûì ñëîâîì unsigned (unsigned
char, unsigned short int è ò. ä.).
×òî êàñàåòñÿ òèïà char ðåàëèçàöèÿ âïðàâå âûáèðàòü, áóäåò îí çíàêîâûì èëè áåççíàêîâûì.  ÷àñòíîñòè, ó gcc ýòî ìîæåò áûòü çàäàíî êëþ÷îì ïðè êîìïèëÿöèè.
Ðàçìåð áåççíàêîâîãî òèïà ñîâïàäàåò ñ ðàçìåðîì ñîîòâåòñòâóþùåãî
çíàêîâîãî òèïà.
Ñòàíäàðò ÿçûêà C íå óêàçûâàåò, êàêèì èç òð¼õ îñíîâíûõ ñïîñîáîâ
(ïðÿìîé êîä, îáðàòíûé êîä, äîïîëíèòåëüíûé êîä) ïðåäñòàâëåíû îòðèöàòåëüíûå ÷èñëà.  ïðîöåññîðàõ x86 èñïîëüçóåòñÿ äîïîëíèòåëüíûé êîä
(two's complement), ìû áóäåì ïðèâîäèòü ïðèìåðû èìåííî äëÿ òàêîãî
ñïîñîáà õðàíåíèÿ.
Èç îïðåäåëåíèÿ äîïîëíèòåëüíîãî êîäà ñëåäóåò, ÷òî ñîîòâåòñòâèå ìåæäó áåççíàêîâûìè è çíàêîâûìè òèïàìè òàêîå:
unsigned char
signed char
0
1
2
...
127
128
129
...
253
254
255
0
1
2
...
127
−128
−127
...
−3
−2
−1
Àíàëîãè÷íî ñîîòâåòñòâóþò äðóã äðóãó áåççíàêîâûé è çíàêîâûé int
è ïðî÷èå öåëûå òèïû.
 ÿçûêå C íå ïðîèñõîäèò îøèáêè â ñëó÷àå âûïîëíåíèÿ ïåðåíîñà åäèíèöû â íåñóùåñòâóþùèé ñòàðøèé áèò â ñëó÷àå áåççíàêîâîãî òèïà è ïðè
ïåðåïîëíåíèè è èçìåíåíèè çíàêîâîãî ðàçðÿäà çíàêîâîãî òèïà.
Äëÿ öåëûõ ÷èñåë îïðåäåëåíû áèòîâûå îïåðàöèè &, |, ^ (èñêëþ÷àþùåå
¾èëè¿),~ è áèòîâûå ñäâèãè <<, >>. Âàæíî ïîíèìàòü, ÷òî &, |, ~ îòëè÷àþòñÿ îò ëîãè÷åñêèõ îïåðàöèé &&, || è !: íàïðèìåð, 7 & 8 == 0, íî 7 &&
8 == 1.
Áèòîâûå îïåðàöèè ìîæíî èñïîëüçîâàòü äëÿ óñòàíîâêè íóëÿ èëè åäè2
Òèïû äàííûõ
íèöû â îïðåäåë¼ííûé áèò ÷èñëà. Íàïðèìåð, äëÿ óñòàíîâêè 1 â áèò k
÷èñëà a ìîæíî èñïîëüçîâàòü
a |= (1 << k);
äëÿ óñòàíîâêè òóäà íóëÿ ïîõîæóþ îïåðàöèþ
a &= ~(1 << k);
à äëÿ ïðîâåðêè çíà÷åíèÿ k-ãî áèòà ÷èñëà a ìîæíî ñðàâíèòü ñ íóë¼ì ÷èñëî
(a >> k) & 1
Âñåãäà áåðèòå îïåðàöèè ñäâèãà â ñêîáêè! Ïðèîðèòåò îïåðàöèè ñäâèãà
ìåíüøå, ÷åì îïåðàöèè ñëîæåíèÿ, ïîýòîìó a << b + c ñîîòâåòñòâóåò a <<
(b + c), ÷òî â áîëüøèíñòâå ñëó÷àåâ íå ÿâëÿåòñÿ òåì, ÷òî âû îæèäàåòå.
Áèòîâûå îïåðàöèè òàêæå èñïîëüçóþòñÿ äëÿ óñòàíîâêè è ñíÿòèÿ ôëàãîâ êîíñòàíò, îáû÷íî ðàâíûõ ñòåïåíÿì äâîéêè: 1, 2, 4, 8, . . . Ýòî äà¼ò
âîçìîæíîñòü õðàíèòü â îäíîé ïåðåìåííîé òèïà unsigned int çíà÷åíèÿ
32 ðàçëè÷íûõ ôëàãîâ. Íàïðèìåð, â óñëîâèÿõ òîòàëüíîé íåõâàòêè ïàìÿòè
â 32 áèòàõ ìîæíî ñîõðàíèòü èíôîðìàöèþ î 32 ñäàííûõ (èëè íåñäàííûõ)
ýêçàìåíàõ ñòóäåíòà:
#define IS_CALCULUS_PASSED
1
#define IS_ALGEBRA_PASSED
2
#define IS_PROGRAMMING_PASSED 4
...
int student_result = 0;
/* ñäàëè ïðîãðàììèðîâàíèå */
student_result |= IS_PROGRAMMING_PASSED;
/* ñäàëè ëè àëãåáðó? */
if (student_result & IS_ALGEBRA_PASSED)
...
3
Âåùåñòâåííûå ÷èñëà
Ñòàíäàðò íå îïðåäåëÿåò òî÷íîãî ñïîñîáà õðàíåíèÿ âåùåñòâåííûõ ÷èñåë. Íàèáîëåå ÷àñòî óïîòðåáëÿåòñÿ ôîðìàò ÷èñåë ñ ïëàâàþùåé çàïÿòîé,
îïèñàííûé â ñòàíäàðòå IEEE 754.
Ïðè âû÷èñëåíèè âûðàæåíèé ñ âåùåñòâåííûìè ÷èñëàìè âîçìîæíû ïîòåðè òî÷íîñòè, î êîòîðûõ âàì ïîäðîáíî ðàññêàçûâàëè íà ëåêöèÿõ ïî
ïðåäñòàâëåíèþ äàííûõ.  êà÷åñòâå ïðèìåðà çàìåòèì, ÷òî öèêë
3
Òèïû äàííûõ
float a = 1.0;
while (a != 0.0)
a /= 2.0;
ñäåëàåò âïîëíå îïðåäåë¼ííîå êîíå÷íîå ÷èñëî èòåðàöèé, à öèêë
float a;
for (a = 0.0; a != 1.0; a += 0.1)
;
áóäåò áåñêîíå÷íûì.
4
Ñòðóêòóðû è îáúåäèíåíèÿ
Ïåðå÷èñëþ îñíîâíûå ôàêòû î ñòðóêòóðàõ, êîòîðûå ìîãóò âûçâàòü
çàòðóäíåíèå. Âî-ïåðâûõ, èìÿ ñòðóêòóðû íå ÿâëÿåòñÿ èìåíåì òèïà â C:
îáúÿâèâ struct s, ìîæíî çàâåñòè ïåðåìåííóþ òèïà struct s, íî íå òèïà s (â îòëè÷èå îò C++). Âïîëíå äîïóñòèìû àíîíèìíûå ñòðóêòóðû. Â
ñëåäóþùåì ïðèìåðå äâå ñòðóêòóðû ïî ñóòè îäèíàêîâû, íî ïðèñâàèâàíèå
ìåæäó íèìè íåâîçìîæíî:
struct
{
int a, b;
} a;
struct s
{
int a, b;
} b;
Êàê âèäíî èç ïðåäûäóùåãî ïðèìåðà, ïðè îïðåäåëåíèè ñòðóêòóðû ìîæíî
ñðàçó îïðåäåëèòü ïåðåìåííóþ òàêîãî òèïà.
Ïðè õðàíåíèè ñòðóêòóð âàæíî ïîíèìàòü, ÷òî ðàçìåð ñòðóêòóðû ìîæåò áûòü áîëüøå, ÷åì ñóììàðíûé ðàçìåð å¼ ýëåìåíòîâ: ýëåìåíòû ñòðóêòóðû âûðàâíèâàþòñÿ ïî îïðåäåë¼ííûì ïðàâèëàì. Íàïðèìåð, ñòðóêòóðà
struct
{
int a;
char c;
int b;
};
4
Òèïû äàííûõ
îáû÷íî áóäåò çàíèìàòü 12 áàéò (ìåæäó tt char c è int b áóäóò âñòàâëåíû
òðè äîïîëíèòåëüíûõ áàéòà âûðàâíèâàíèÿ). Áàéòû âûðàâíèâàíèÿ ìîãóò
áûòü òàêæå äîáàâëåíû â êîíåö ñòðóêòóðû, íî íå â íà÷àëî: àäðåñ ïåðâîãî
ýëåìåíòà ñòðóêòóðû âñåãäà ñîâïàäàåò ñ àäðåñîì ñàìîé ñòðóêòóðû.
Ðàçëè÷íûå ñïîñîáû âûðàâíèâàíèÿ ìîãóò ïðèâåñòè ê ïðîáëåìàì ïðè
÷òåíèè ñòðóêòóð, ðàíåå çàïèñàííûõ â ôàéë íà êîìïüþòåðå ñ äðóãîé ÎÑ
èëè àðõèòåêòóðîé.
Äëÿ îáðàùåíèÿ ê ýëåìåíòó ñòðóêòóðû èñïîëüçóåòñÿ òî÷êà, äëÿ îáðàùåíèÿ ê ýëåìåíòó ñòðóêòóðû ÷åðåç àäðåñ ñòðóêòóðû èñïîëüçóåòñÿ ¾ñòðåëî÷êà¿ ->. Âîîáùå ãîâîðÿ, â C çàïèñü p->a ÿâëÿåòñÿ áîëåå êðàòêîé çàïèñüþ äëÿ (*p)->a (ñêîáêè âàæíû: ýòî íå òî æå ñàìîå, ÷òî *p->a).
Ñóùåñòâóåò òàêæå îñîáûé âèä ýëåìåíòîâ ñòðóêòóðû: áèòîâûå ïîëÿ,
äëÿ êîòîðûõ óêàçûâàåòñÿ òî÷íîå êîëè÷åñòâî áèò, âûäåëåííûõ ïîä ýòî
ïîëå. Íàïðèìåð, òàêàÿ ñòðóêòóðà òî÷íî ñîîòâåòñòâóåò òèïó float â ñòàíäàðòå IEEE 754:
struct float
{
unsigned int significand: 23;
unsigned int exponent: 8;
unsigned int sign: 1;
};
Áèòîâûå ïîëÿ ïîçâîëÿþò ðåàëèçîâàòü ôëàãè áåç îáúÿâëåíèÿ áîëüøîãî êîëè÷åñòâà ìàêðîñîâ (#define). Ïðèìåð ïðî ýêçàìåíû ìîæåò áûòü
ïåðåïèñàí òàê:
struct exam_list
{
unsigned int IS_CALCULUS_PASSED: 1;
unsigned int IS_ALGEBRA_PASSED: 1;
unsigned int IS_PROGRAMMING_PASSED: 1;
...
};
struct exam_list student_result;
student_result.IS_PROGRAMMING_PASSED = 1;
Âñå ÷ëåíû îáúåäèíåíèÿ union ðàçìåùàþòñÿ â ïàìÿòè, íà÷èíàÿ ñ îäíîãî è òîãî æå àäðåñà. Îáúåäèíåíèÿ ïîçâîëÿþò ýêîíîìèòü ïàìÿòü, åñëè
â îäíèõ è òåõ æå ïåðåìåííûõ ìîæåò ïîíàäîáèòüñÿ õðàíèòü çíà÷åíèÿ ðàçíûõ òèïîâ, è ðàçáèðàòü âíóòðåííþþ ñòðóêòóðó òèïîâ. Íàïðèìåð, ìîæíî
çàïèñàòü
5
Òèïû äàííûõ
union Float
{
struct float sf;
float f;
} u;
è, ïðèñâîèâ äëÿ ïðèìåðà u.f = 1.0, ñìîòðåòü íà u.sf.significand,
è u.sf.sign. Æåëàþùèå ìîãóò òàêèì îáðàçîì èçó÷èòü,
êàê íà ñàìîì äåëå ïðåäñòàâëÿþòñÿ âåùåñòâåííûå ÷èñëà â ñòàíäàðòå IEEE
754.
u.sf.exponent
5
Ïåðå÷èñëåíèÿ
Ïåðå÷èñëåíèÿ enum èñïîëüçóþòñÿ, åñëè íóæíî ñîçäàòü òèï, ñîñòîÿùèé èç çàðàíåå îïðåäåë¼ííûõ êîíñòàíòíûõ çíà÷åíèé:
enum suite { SPADE, HEART, DIAMOND, CLUB };
Çíà÷åíèÿì ìîæíî òàêæå óêàçûâàòü ñîîòâåòñòâóþùèå ÷èñëîâûå çíà÷åíèÿ.  ÿçûêå C êîíñòàíòû ïåðå÷èñëåíèÿ èìåþò ãëîáàëüíóþ îáëàñòü
âèäèìîñòè, ïîýòîìó èñïîëüçîâàíèå èõ íå î÷åíü óäîáíî (ýòà ïðîáëåìà ðåøåíà â Ñ++ ââåäåíèåì ïðîñòðàíñòâ èì¼í).
6
Download