You are on page 1of 33

NAPREDNO

PROGRAMIRANJE
P2 Osnovni tipovi u
programskom jeziku C
Doc. dr. sc. Marijan Herceg
Doc. dr. sc. Josip Job
2015./2016.

Programski jezik C
- neformalno
Imperativni jezik (nasuprot deklarativnom)
Naredbe se izvravaju redom i u skladu sa znaenjem
mijenjaju stanje programa.

Stanje

Varijable i dijelovi memorije - objekti

Naredbe

Izrazi
Funkcije
Blokovi

SQL:

SELECT * FROM tblAdresar


WHERE tblAdresar.id < 10

Python:

small_nums = [x for x in range(20) if x < 5]


small_nums = []
for i in range(20):
if i < 5:
small_nums.append(i)

Programski jezik C
- neformalno

127 razina ugnjedenja blokova


63 razine ugnjedenja uvjetnih ukljuivanja datoteka
63 ugnjedena deklaratora u zagradama unutar punog deklaratora
63 ugnjedenih izraza u zagradama unutar punog izraza
63 znaajnih poetnih znakova kod internih identifikatora i naziva makroa
31 znaajnih poetnih znakova kod eksternih identifikatora
4095 eksternih identifikatora u jednoj jedinici prevoenja
4095 makro identifikatora u jednoj jedinici prevoenja
511 identifikatora sa blokovskim dometom unutar jednog bloka
127 parametera u jednoj definiciji funkcije
127 parametara (argumenata) u jednom pozivu funkcije
127 parametara u jednoj makro definiciji
127 parametara u jednom makro pozivu
4095 znakova u jednoj (logikoj) liniji izvornog koda
4095 znakova u string konstanti (nakon spajanja)
65535 bajtova u jednom objektu (in a hosted environment only)
15 nivoa ugnjedelja ukljuenih datoteka (putem #include direktive)
1023 case labela u jednoj switch naredbi
1023 lanova strukture ili unije
1023 elemenata u jednom brojivom tipu
63 razina ugnjedenja u deklaraciji jedne strukture ili unije

Osnovni tipovi u programskom


jeziku C

to je tip
Tip je svojstvo varijable koja odreuje koje vrijednosti
ona moe imati i to se s njom moe raditi.
C jezik je eksplicitno tipiziran jezik -> svakoj varijabli
tip mora biti zadan od strane programera -> prilikom
njene deklaracije
C je statiki tipiziran jezik -> jednom postavljen tip vie
se ne moe mijenjati
Svaka varijabla ima tip, svaki izraz ima tip, (skoro) sve
ima tip
Osnovni tipovi - izvedeni tipovi
Definiran skupom vrijednosti i operacijama
Tip ne mora odreivati fiziku reprezentaciju vrijednosti

Cjelobrojni (integer) tipovi

char

minimum 8 bita, najee upravo 8 bita

zahtijeva se da bude najmanja adresiva jedinica ciljne platforme - byte, tj. da


njegova veliina bude jednaka irini memorije.

short (int)

minimum 16 bita, najee upravo 16 bita.

minimum 16 bita, najee 32 bita.

uobiajen opseg -2147483648, 2147483647 ] ako je oznaen ili [0, 4294967295], ako
je neoznaen

uobiajeno je da predstavlja najprirodniju veliinu za ciljnu platformu.

long (int)

najmanje 32 bita, najee 32 bita.

uobiajen opseg [-32768, 32767] ako je oznaen ili [0, 65535], ako je neoznaen

int

uobiajen raspon [-128, 127] ako je oznaen ili [0, 255], ako je neoznaen

uobiajen opseg -2147483648, 2147483647 ] ako je oznaen ili [0, 4294967295], ako
je neoznaen

long long (int)

najmanje 64 bita, najee upravo 64 bita.


dio C99 standarda

Modifikatori
Mogui modifikatori osnovnih tipova:

char

signed
unsigned

int

signed
unsigned
short
long

Na to se osloniti kada veliine


cjelobrojnih tipova variraju od
platforme do platforme?

Odgovor je u stdint.h zaglavlju. Ako elimo da integer tip


bude:

tono odreene veliine

intN_t i uintN_t gdje N moe biti bilo koji prirodan broj


Postojanje ovih tipova nije obvezno, ali ako je neki od integer
tipova irok 8, 16, 32 ili 64 bita onda odgovarajui tip mora biti
definiran. to su posljedice ovoga?

minimalno odreene veliine

najmanji minimalno te veliine

int_leastN_t i uint_leastN_t, za N 8, 16, 32 i 64


postoje uvijek.
najbri minimalno te veliine

int_fastN_t i uint_fastN_t, za N 8, 16, 32 i 64


postoje uvijek.

dovoljno velik da u sebi dri pokaziva, tj. adresu

intptr_t i uintptr_t, ali nisu obavezni. (Zato?)

najvei integer tip

intmax_t i uintmax_t

Da li je char tip oznaen ili


neoznaen?
C standard ostavlja konkretnom kompajleru da
specificira da li je char tip podrazumjevano oznaen ili
neoznaen. Recimo:

Kod kompajlera za x86 (GNU/Linux i Microsoft Windows) char


tip je obino oznaen
Kod kompajlera za PowerPC i ARM procesore char tip je
obino neoznaen

Prenosivost koda moe biti naruena ako se oslanja na


podrazumjevanu oznaenost!
Po C99 standardu, u zaglavlju limits.h mora biti
definiran simbol CHAR_MIN. Ako je nula, char je
podrazumjevano neoznaen, i obrnuto.

signed ili unsigned char?


#include <stdio.h>
#include <limits.h>
int main (void)
{
if (CHAR_MIN == 0)
{
printf("char is unsigned.);
}
else
{
printf("char is signed.);
}
return 0;
}

Rjeenje za ve postojei
kod
Osnovno rjeenje je preraditi kod
Neki kompajleri, kao to je GCC nude opciju kojom se
odreuje koja e biti podrazumjevana oznaenost char
tipa:
-fsigned-char i -funsigned-char.

Pokazivai
Najbolje je na pokazivae gledati kao na poseban tip.
U tom smislu, zvjezdicu zalijepiti za tip na koji se pokazuje:

int* p;

umjesto:
Pokazivai na objekte:
float* p;
p = &x;
*p = y;
z = *p;

Nul (NULL) pokaziva:


#include <stddef.h>
p = NULL;
*p = y;

int *p;
Pokazivai na funkcije:
int* (*p)(int a, float b);
int* foo(int x, float y);
p = foo;
ip = p(n, m);

Pokaziva na void (void):


void* p;
p = &x;
*p = y;
*(int*)p = y;

Korisniki tipovi
typedef nasuprot #define
Za definiranje novih tipova moe se koristiti #define i typedef
#define INT_PTR int*
typedef int* int_ptr;
Primjer uporabe:
INT_PTR ptr1, ptr2;
int_ptr ptr3, ptr4;
Primjer: poslije pretprocesora prva linija izgleda ovako
int* ptr1, ptr2;
to tu nije u redu?
Savjet 1: Za nove tipove koristiti typedef.
Savjet 2: Svaka deklaracija varijable u zasebnom redu.

Tipovi sa pominim zarezom


(float tipovi)

Tipovi sa pominim zarezom slue za izraavanje realnih brojeva.


Postoje tri tipa sa pominim zarezom koji se razlikuju po veliini i
preciznosti:

float zauzima 32 bita


double dupla preciznost zauzima 64 bita
long double (uveden u C99)

U standardnom zaglavlju float.h definirane su minimalne i


maksimalne vrijednosti svakog tipa sa pominim zarezom, skupa s
jo nekim korisnim vrijednostima, kao to su preciznost i slino.

Tip

Znak

Eksponent

Mantisa

Ukupno bita

float

23

32

double

11

52

64

Brojivi tipovi - Enumeracije


Uvedeni u C89 standardu
Predstavljaju jednu vrijedost iz skupa navedenih
vrijednosti. Vrijednosti su C simboli.
Kako to radi:

svakoj simbolikoj vrijednosti iz enum tipa dodjeljuje se


jedinstveni cijeli broj
svako mjesto gdje se spominje simbol iz enum-a zamjenjuje se
s odgovarajuim brojem od strane kompajlera

Enum primjer

Prvom navedenom simbolu


pridruuje se 0, osim ako
eksplicitno nije pridruen neki
drugi broj.
enum Days
{
Sunday = 1,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
};
Svakom narednom simbolu
pridruuje se broj pridruen
prethodnom simbolu uvean
za 1

Ponekad (obino u starijim kodovima) koristi


se #define da bi se napravio skup simbola
#define
#define
#define
#define
#define
#define
#define

Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday

1
2
3
4
5
6
7

Veliina enum tipa


Enum tip se svodi na cjelobrojni tip
Ostavljeno je kompajleru da odlui na koji konkretan tip
e svesti odreeni enum tip, ali veliina tog cjelobrojnog
tipa ograniena je standardom i to na dva naina:

Mora biti dovoljno velik (irok) da bi smjestio sve vrijednosti


koje su u enum-u definirane
ali ne vei od veliine int tipa.

Neki kompajleri nude mogunost pravljenja enum-a koji


su vei od int tipa

Oznaenost enum tipa


Kao veliina cjelobrojnog tipa tako i njegova oznaenost
je ostavljena kompajleru na izbor
Ne mora biti ista za sve enum-e
Obino ako postoji simbol s negativnom vrijednou
enum e biti predstavljen oznaenim tipom, u suprotnom
neoznaenim. Meutim, to moe biti tako, ali i ne
mora!!!
Zato se ne oslanjati na ovo!

Konverzije tipova

Konverzije tipova
Kada se dva razliita tipa kombiniraju u odreenim
operacijama nastaje potreba za konverzijom tipova
Konverzija moe biti:

Implicitna

Dodjela
Poziv funkcije

Prosljeivanje parametara
Povratna vrijednost

Aritmetike konverzije Najei izvor problema ako se ne


poznaju dovoljno dobro.
Promocija tipova

Eksplicitna

Takozvano kastanje (engl. casting) (int)x

Tipovi konstanti (literala)


Svaki operand (izraz) ima tip!
Kod literala tip je odreen sufiksom i postojanjem
decimalne toke
Primjeri:
2U
3L 3l 31
5UL
7LL
11ULL
13.0
17.
19.0F
23.F
29.0L
31.L

-37
051
// 41
0x2b
// 43
0xFFFFFFD1 // -47
3.14159
6.02e23
1.6e-19

// 3.14159
// 6.02 x 10^23
// 1.6 x 10^-19

Promocije tipova
Promocija tipova je specijalni sluaj implicitne konverzije.
Promocije cjelobrojnih tipova

U operacijama gdje sudjeluju cjelobrojni tipovi manji od int


(dakle: char ili short):

operandi se prvo promoviraju u odgovarajui int (oznaeni ili


neoznaeni),
obavlja se operacija,
rezultat se svodi na poetni tip odsjecanjem vika bitova.
char a;
char b;
char c = a + b;

Promocije float-ova

Tip float se promovira u double

Aritmetike konverzije:
primer
double polovina = 1/2;
Koja e biti vrijednost varijable polovina?
Zato?
Kojeg tipa su djeljenik i djelitelj?
Kojeg tipa je kolinik?
Svaki operand, tj. izraz, ima tip pa tako i izraz 1/2
ima tip i taj tip nema veze s tipom operanda s lijeve
strane jednakosti!

Aritmetike konverzije: primjer nastavak


Konstante 1 i 2 su integer tipa.
Ako su oba operanda int i tip rezultata je int. Dakle,
cjelobrojni rezultat ovog izraza je 0.
double polovina = 1.0/2.0;
ali dovoljno je i ovako:
double polovina = 1.0/2;
U sluaju da su x i y integer tipa:
double kolicnik = ((double)x)/y;

Aritmetike konverzije
Brojani tipovi su poredani po rangovima od najmanjeg do najveeg
ovako:
char, short, int, long, long long, float, double, long double
Ukoliko u binarnoj operaciji sudjeluju dva operanda razliitog tipa, onda
se operand iji je tip manjeg ranga konvertira u tip drugog operanda
Ukoliko u binarnoj operaciji tipovi operanada nisu iste oznaenosti,
onda se operand iji je tip oznaen konvertira u neoznaeni tip.
Pouka: biti jako paljiv s ovim!
Najbolje je da osim konverzije iz nekog cjelobrojnog tipa u tip s
pominim zarezom uvijek koristimo eksplicitne konverzije.
Kompajler e obino generirati upozorenja za dio problematinih
sluajeva.

Potencijalni problemi prilikom


konverzija
Opasne konverzije

Gubitak vrijednosti: Konverzija veeg (ireg) tipa u manji (ui)


Gubitak znaka: Konverzija izmeu oznaenih i neoznaenih
tipova moe dovesti do promjene znaka
Gubitak preciznosti: Konverzija preciznijeg u neprecizniji tip

Sigurne konverzije

Konverzija cjelobrojnog tipa u vei (iri) cjelobrojni tip


Konverzija tipa s pominim zarezom u vei (iri i precizniji) tip s
pominim zarezom

Konverzije pokazivaa
Konverzije koje ne treba praviti su:

izmeu pokazivaa i integer tipa.

Ova konverzija nije definirana standardom, tj. svaki kompajler moe


izabrati svoju definiciju.
Neki put je neizbjeno; npr. kod pristupanja memorijski mapiranim
registrima ili drugim aspektima specifinim za ciljnu platformu.

izmeu pokazivaa na dva razliita tipa.

Problem moe nastati uslijed neodgovarajueg poravnanja


(poravnanje e biti detaljnije obraeno kasnije)

uint8_t p1[4];
uint32_t* p2;
p2 = (uint32_t*)p1; /* incompatibile alignment */

Konverzije pokazivaa

Validne konverzije:

Konverzije koje moraju biti eksplicitne:

Iz pokazivaa na void (void*) u pokaziva na neki drugi tip, i


obrnuto.
Konverzija simbola NULL u pokaziva. NULL je praktino konstanta
nula (u mnogim implementacijama konvertirana u pokaziva na void)
i to predstavlja jedinu validnu konverziju iz integera u pokaziva.
Pokaziva ija je vrijednost NULL u pokaziva na bilo koji drugi tip.
Savjet: koristiti simbol NULL, a ne 0.

Pokaziva na objekt bilo kojeg tipa u pokaziva na objekt drugog tipa.


Pokaziva na funkciju jednog tipa u pokaziva na funkciju drugog tipa.

Nevalidne konverzije:

Pokaziva na funkciju u pokaziva na objekt (ili pokaziva na void) i


obrnuto.

Little i Big endian


(mala i velika krajnost)
Uzmimo da je irina memorije na nekom procesoru 8 bita, tj. da svakih 8
bita ima svoju adresu.

Pitanje: Kako emo u memoriju takvog procesora smjestiti 32-bitnu


vrijednost?

Odgovor: Podijelit emo 32-bitnu vrijednost na 4 8-bitne, npr.


vrijednost 0x0A0B0C0D se moe podijeliti na sljedea etiri dijela:
0x0A, 0x0B, 0x0C i 0x0D, poredanih po znaajnosti, od najvee ka
najmanjoj.
Dva su naina da se ta etiri dijela smjeste u memoriju:

Dijelovi manjeg znaaja idu na manju adresu - Little endian


Dijelovi veeg znaaja idu na manju adresu - Big endian

S kojeg kraja se vrijednosti smijetaju u memoriju najvie ovisi o samom


procesoru. Recimo:

MIPS moe se izabrati LE i BE


Intel - LE
ARM - LE

Little i Big endian


Dio najmanjeg
znaaja se upisuje
prvi = little endian

Di najveeg
znaaja se upisuje
prvi = big endian

Little i Big endian


Ilustracija razlike
1.
2.
3.
4.

Smjesti 0x0A0B0C0D u memoriju kao 32-bitnu vrijednost


(recimo int tipa)
Proitaj te memorijske lokacije kao 2 uzastopne 16bitne vrijednosti
Proitaj te memorijske lokacije kao 4 uzastopne 8-bitne
vrijednosti
Proitane vrijednosti:
16bit access:

LE: 0x0C0D i 0x0A0B


BE: 0x0A0B i 0x0C0D

8bit access:

LE: 0x0D, 0x0C, 0x0B i 0x0A


BE: 0x0A, 0x0B, 0x0C i 0x0D

Razmjena podataka izmeu


raunala
Postoji dogovor oko formata kojim se alju podaci preko
mree. Mreni standard kae: big-endian.
Za prebacivanje u mreni format zvati funkciju hton (hostto-network). Na big-endian raunalima ne radi nita, ali da
bi program bio portabilniji vano je koristiti hton uvijek
prije slanja podataka preko mree.
Analogno postoji i funkcija ntoh (network-to-host) koja
slui za itanje podataka sa mree.
Funkcije za konverziju:

htons() - "Host to Network Short" 16bit


htonl() - "Host to Network Long" 32bit
ntohs() - "Network to Host Short" 16bit
ntohl() - "Network to Host Long" 32bit

You might also like