146
Programování v jazyce C RNDr. Jan Lánský, Ph.D. Katedra softwarového inženýrství MFF UK Katedra informatiky VŠFS (Autor původní verze slajdů: RNDr. Filip Zavoral, Ph.D.) [email protected] http://kocour.ms.mff.cuni.cz/~lansky/

Programov ání v jazyce C

  • Upload
    ramya

  • View
    46

  • Download
    2

Embed Size (px)

DESCRIPTION

Programov ání v jazyce C. RNDr. Jan Lánský, Ph.D. Katedra softwarového inženýrství MFF UK Katedra informatiky V Š FS (Autor původní verze slajd ů : RNDr. Filip Zavoral, Ph.D.) [email protected] http://kocour.ms.mff.cuni.cz/~lansky/. Studijní povinnosti. Zápočet - PowerPoint PPT Presentation

Citation preview

Page 1: Programov ání v  jazyce  C

Programování v jazyce C

RNDr. Jan Lánský, Ph.D.Katedra softwarového inženýrství MFF UK

Katedra informatiky VŠFS

(Autor původní verze slajdů: RNDr. Filip Zavoral, Ph.D.)

[email protected]

http://kocour.ms.mff.cuni.cz/~lansky/

Page 2: Programov ání v  jazyce  C

2

Studijní povinnosti

Zápočet aktivní účast na cvičeních během semestru 'domácí úkoly' (krátké prográmky)

2 povinné 2 dobrovolné (nejsou podmínkou zápočtu, ale lze je použít u zkoušky)

Zkouška Musíte mě přesvědčit o vašich znalostech Ústní na základě přípravy napsání programu

na PC s možností použít domácí úkoly (povinné i dobrovolné) žádná další literatura (s výjimkou nápovědy) není povolena

Page 3: Programov ání v  jazyce  C

3

Programování v jazyce C OOP (v C++) ZS LS

Obsah předmětu

C++

C C

C++

Nejdůležitější: vlastní praxeNa přednáškách se nikdo nikdy programovat

nenaučil

Page 4: Programov ání v  jazyce  C

4

Obsah přednášky

Přednáška Překlad programů, spojování Základní vlastnosti C a C++, odlišnosti od jiných prog. jazyků Datové typy, operátory a řídící konstrukce Pole a ukazatele Standardní knihovny Programování není zápis algoritmů

Cvičení Praktické programování Microsoft Visual Studio .NET 2008 Ladění programů (!)

Prosíím, já jsem napsal program a ono to řeklo 'Váš program provedl neplatnou instrukci a bude ukončen '. Co mám dělat?

Page 5: Programov ání v  jazyce  C

5

Pascal vs. C++

Úvod do Programování, Programování heslo: programování = zápis algoritmů algoritmické myšlení, algoritmizace problému soustředění se na řešení problému formulace algoritmu a jeho zápis v nějakém formalismu (jazyku) základní datové a řídící struktury nedůležité: kontrola vstupů, uživatelské rozhraní, obedněnost, vazba

na OS a HW, přenositelnost, optimalizace, udržovatelnost

výuka (v) Pascalu dobrý jazyk pro zápis algoritmů nezatěžuje technickými detaily (alokace paměti, vazba na OS, ...) slabá podpora pro kontrolu vstupů, uživatelské........

Page 6: Programov ání v  jazyce  C

6

Pascal vs. C++

Programování v jazyce C++, OOP heslo: programování = vývoj software důležité: kontrola vstupů, uživatelské rozhraní, obedněnost, vazba na

OS a HW, přenositelnost, optimalizace, udržovatelnost zvládnutí knihoven a vývojových nástrojů

výuka (v) C++ standardní jazyk pro vývoj software další jazyky vycházejí z C++ (Java, C#, ...) dobrá podpora pro kontrolu vstupů, uživatelské........ nutnost zvládnout technické detaily (alokace paměti, vazba na OS..) velké množství hotového kódu (knihovny, komponenty, ...)

'Vše' již bylo naprogramován

o

Page 7: Programov ání v  jazyce  C

7

Literatura

Základní učebnice a popis jazyka Miroslav Virius: Programování v C++ (ČVUT, 2. vydání 2004)

Miroslav Virius: Pasti a propasti jazyka C++ (Brno, 2. vydání 2005) Bjarne Stroustrup: The C++ Programming Language (3rd ed.) Bruce Eckel: Myslíme v jazyku C++ (Thinkinkg in C++ 2nd ed.)

C++ In-depth aneb Jak správně C++ používat - pro ty, kdo již C++ nějak znají Scott Meyers: Effective C++ (2nd ed.), More Effective C++ Herb Sutter: Exceptional C++, More Exceptional C++ Andrew Koenig, Barbara E. Moo: Accelerated C++ Practical Programming by

Example Nicolai Josuttis: The C++ Standard Library – A Tutorial and Reference James Coplien: Advanced C++ Programming Styles and Idioms Que: ANSI/ISO C++ Professional Programmer's Handbook Andrei Alexandrescu: Modern C++ Design Generic Programming and Design

Patterns Applied

Normy ISO/IEC 9899: Programming languages - C (1999) ISO/IEC 14882, ANSI: Programming languages - C++ (1998, 2003)

Page 8: Programov ání v  jazyce  C

8

Nevhodná literatura - nepoužívat!

Martin Beran: Učebnice Borland C++ - hrubé chyby

Jan Pokorný: Rukověť uživatele Borland C++ - staré, BC 3.1

Vladimír Rudolf: ABC programátora v C++ - neúplné, zastaralé

Dirk Louis: C und C++ — Programierung und Referenz - chyby

Dalibor Kačmář: Jazyk C — učebnice pro střední školy – chyby

Brodský, Skočovský: Operační systém Unix a jazyk C – neúplné, zastaralé

Eric Gunnerson: Začínáme programovat v C# – C# není C++

Page 9: Programov ání v  jazyce  C

9

Historie

1970-73 první verze C, společný vývoj s UNIXem1973 přepsání jádra UNIXu do C1978 Kerninghan, Ritchie: The C Programming Language1980 standardy – ANSI X3J11, od r. 1999 ISO 98991980 AT&T - "C with Classes"1983 poprvé název C++ (Rick Mascitti)1985 Stroustrup: The C++ Programming Language1989 ANSI X3J16 norma C++2003 nejnovější ISO/ANSI norma C++

Normy se vyvíjí, aktuální překladače o několik let zpětImplementace novinek často nekorektní nebo neefektivní (STL)

Page 10: Programov ání v  jazyce  C

10

hello.c

#include <stdio.h>#include <conio.h>

int main( int argc, char ** argv){ printf( "Hello\n"); getch(); return 0;}

Page 11: Programov ání v  jazyce  C

11

hello.c

#include <stdio.h>#include <conio.h>

int main( int argc, char ** argv){ printf( "Hello\n"); getch(); return 0;}

tělo funkce

hlavička funkce

příkaz

deklarace knihovních funkcí

direktiva preprocesoru

vložení souboru

formální parametr

y

název funkce

typ návratové hodnoty

skutečné parametr

yvolání funkce

bez parametr

ůsložené

závorky BEGIN END

Page 12: Programov ání v  jazyce  C

12

Struktura programu

Program se skládá z modulů Překládány samostatně kompilátorem Spojovány linkerem

Modul z pohledu programátora Soubor s příponou .cpp (.c)

Hlavičkové soubory Soubory s příponou .h Deklarují (a někdy i definují) identifikátory používané ve více

modulech Vkládány do modulů direktivou include

Direktivu zpracovává preprocesor čistě textově Preprocesor je integrován v kompilátoru jako první fáze překladu

Modul z pohledu kompilátoru Samostatná jednotka překladu Výsledek práce preprocesoru

Page 13: Programov ání v  jazyce  C

13

Překlad jednoho modulu a sestavení

.cpp

.h

CC .obj Link .exe

.obj.obj.obj.obj.obj.lib

kompilacespojování(linkování

)

knihovnystandardní i

jiné

knihovní headery

objektový modul

(přeložený kód)

spustitelný

program

Page 14: Programov ání v  jazyce  C

14

Modul - ucelená funkčí jednotkamodul.cpp (.c) - implementacemodul.h - definice rozhraní

Oddělený překlad - dělení na moduly

fotbal.cpp

fotbal.h

hriste.cpp hrac.cpp mic.cpp

hriste.h hrac.h mic.h

rozdělení projektu do modulů

a vytváření headerů je umění,

nedá se to naučit na přednášce

Page 15: Programov ání v  jazyce  C

15

Překlad více modulů – oddělený překlad

.c

.h .h

CC .obj Link .exe

.obj.obj.obj.obj.obj.lib

.obj.obj.obj

kompilace jednoho modulu

knihovnyknihovní headery

vlastní headery

.c

.c.c

další moduly

Page 16: Programov ání v  jazyce  C

16

Překladače a vývojová prostředí

Windows - překladač součástí integrovaného prostředí MS Visual Studio - Visual C++ (VC6.0, .Net, .Net2008) integrovaný make, linker, debugger klikabilní konfigurace další překladače - Borland C++ Builder, Intel, Watcom

Unix (Linux) - samostatné programy, příkazová řádka gcc make - pro 'opravdové' programátory pokusy o vývojová prostředí (kDevelop)

raději nepoužívat

Page 17: Programov ání v  jazyce  C

17

Integrované vývojové prostředí

.c

.h .h

CC Link .exe

.obj.obj.obj.obj.obj.lib

.obj.obj.obj.c

.c

debugger

projekt

editor

Page 18: Programov ání v  jazyce  C

18

Make

.c

.h .h

CC Link .exe

.obj.obj.obj.obj.obj.lib

.obj.obj.obj.c

.c

makemakefile

Page 19: Programov ání v  jazyce  C

19

Program a modul

Program v C++ nemá (vnořovanou) blokovou strukturuNeexistuje "hlavní blok"

Běh programu začíná vyvoláním funkce main Před funkcí main běží inicializace běhového prostředí, po ní úklid Funkce main musí mít tuto hlavičku:

int main( parametry příkazové řádky)

Modul: posloupnost globálních deklarací a definic Deklarace

Oznámení překladači, že identifikátor existuje Určení některých vlastností (typ, parametry)

Definice Doplnění zbývajících vlastností (kód funkce, obsah struktury) Překladač vygeneruje kód funkce, vyhradí místo pro proměnnou

Page 20: Programov ání v  jazyce  C

20

Funkce

Základní programová jednotka je funkceNeexistují vnořené funkceZačátek programu – funkce main

int fce1( int x, int y){ return x+y;}

int fce2( int a){ return fce1( 1, 2*a+5);}

int main( int argc, char** argv){ ...}

int fce2( int a){ int fce1( int x, int y) { return x+y; }

return fce1( 2*a+17);}

vnořené

funkce nelze!

začátek programu argumenty z příkazové řádky

později

hlavička funkce

tělo funkce

Page 21: Programov ání v  jazyce  C

21

Funkce - návratový typ

Typ funkce = typ návratové hodnotyHodnota se vrací pomocí klíčového slova return

Speciální typ void - 'prázdný' typ ekvivalent procedury Pascalu

int fce1( int x, int y){ return x+y;}

void fce2( char* text){ printf( text);}

void fce3( char* text){ if( ! text) return; printf( text);}návrat celočíselné

hodnoty

návrat z funkce

typ funkce

Page 22: Programov ání v  jazyce  C

22

Parametry funkce

Pevný počet, pevný typ možnost proměnného počtu parametrů - printf

Parametry jsou odděleny čárkouU každého parametru musí být uveden jeho typFunkce bez parametrů - void

int fce1( int x, int y, float z){ ...}

int fce2( double a, char* str){ ...}

int fce3( void){ ...}

int fce4( int x, y){ ...}

int fce5{ ...}

každý parametr musí

mít typ

Page 23: Programov ání v  jazyce  C

23

Volání funkce

Shoda počtu formálních a skutečných parametrůKompatibilita typů formálních a skutečných parametrůI funkce bez parametrů musí obsahovat operátor ()Návratová hodnota - lze ignorovat

int fce1( int x, int y, float z){ ... }

int fce3( void){ ... }

int fce2( int a){ fce1( a, 1, a); fce3(); return 0;}

int fce4( int x, int y, float z){ ... }

int fce5( int a){ fce4; fce4( a, 1); fce4( a, 1, "ahoj");}

Page 24: Programov ání v  jazyce  C

24

Lokální proměnné

Definice lokálních proměnných C: na začátku těla funkce (přesněji: na začátku bloku) C++: kdekoliv v těle funkce

Možná inicializace – při každém běhu funkce neinicializovaná proměnná – náhodná hodnota !!!

int fce( void){ int x, y; int z = 0; return z + x;}

deklarace celočíselných proměnných

deklarace s inicializací

náhodná hodnota !!!

Page 25: Programov ání v  jazyce  C

25

Příklad - malá násobilka

#include <stdio.h>

int vynasob( int c){ int i = 1, v; if( c < 1 || c > 10) return -1; while( i <= 10) { v = i * c; printf( "%d * %d = %d\n", i, c, v); i = i + 1; } return 0;}

int main(){ int cislo = 7; vynasob( cislo); return 0;}

inicializovaná

celočíselná proměnná

neinicializovaná proměnná

hlavička funkce, formální parametr

definice knihovních

funkcí

konec cyklu

začátek cyklu

kontrola parametrů

okanžitý návrat z funkce

2 * 7 = 14

i++

konec, OK

konec, OK

hlavní program

ignorování návratové hodnoty volání funkce

se skutečným

parametremThe END

Page 26: Programov ání v  jazyce  C

26

Předávání parametrů hodnotou

Všechny parametry se předávají hodnotou'Výstupní' parametry pouze přes ukazatele nebo reference

vymění se jen lokální proměnné

funkce

předají se pouze hodnoty (1, 2), nikoliv 'proměnné'

void swap( int x, int y){ int pom; pom = x; x = y; y = pom;}

void fce( void){ int a = 1; int b = 2; int c = 0; swap( a, b); c = 2 * a + b;}

Page 27: Programov ání v  jazyce  C

27

Globální proměnné

Definice mimo tělo funkceViditelné v jakékoliv funkciMožná inicializace – při startu programuPoužívat s rozvahou!!

pouze pro sdílená dataint g = 1;

void fce( int x){ int z = 2; g = g + z * x;}

int main( void){ fce( 2); fce( 3); return g;}

globální proměnná

formální parametr

skutečný parametr

lokální proměnn

á

co vrátí main ??

Page 28: Programov ání v  jazyce  C

28

Výraz

Norma: "Výraz je posloupnost operací a operátorů specifikující výpočet hodnoty"Přiřazovací 'příkaz' je také výraz

jeho hodnotou je přiřazovaná hodnotaVýrazy mohou mít vedlejší efekty

1

a+b*sin(x)

printf( "Ahoj")

q = &b[17]+*p++

"retezec"

a = b = 0;

if( (x = fnc()) != 0) ...

užitečné:test přiřazované

hodnoty

Page 29: Programov ání v  jazyce  C

29

Příkaz

Příkaz je výraz ukončený ';' (středníkem) složený příkaz - posloupnost příkazů mezi '{' a '}' programová konstrukce

if, if-else, switch, while, do-while, for, break, continue, return, goto

1;a+b*sin(x);printf( "Ahoj");q = &b[17]+*p++;"retezec";

{ 1; a+b*sin(x); printf( "Ahoj"); q = &b[17]+*p++; "retezec";}

jeden složen

ý příkaz

Page 30: Programov ání v  jazyce  C

30

Podmíněný příkaz

if (výraz) příkazif (výraz) příkaz else příkaz

if( a > 1) printf( "OK");

if( a > 1) b = 0; printf( "OK");

if( a > 1) b = 0; printf( "OK");else printf( "nee");

if( a > 1){ b = 0; printf( "OK");}else{ printf( "nee");}

if( a > 1) printf( "OK");else printf( "nee");

syntakticky správně, ale dělá

něco jiného

syntakticky špatně

if( a > 1) { b = 0; printf( "OK");} else { printf( "nee");}

Page 31: Programov ání v  jazyce  C

31

Vnořené podmíněné příkazy

if( a > 1) { if( b > 0) printf( "OK");} else { printf( "nee");}

Syntakticky správně, ale nepřehledné

Na pohled nejasné párování

if( a > 1) { if( b > 0) printf( "OK"); else printf( "nee");}

U vnořených podmínek

vždy používat { }

if( a > 1) if( b > 0) printf( "OK");else printf( "nee");

Page 32: Programov ání v  jazyce  C

32

Vícenásobné větvení – konstrukce switch

switch (výraz) { case konstanta: posloupnost příkazů break; case konstanta: case konstanta: posloupnost příkazů break; default: posloupnost příkazů}

switch( errc) {case 0: b = 0; printf( "OK"); break;case -1: printf( "trochu spatne"); break;case -2:case -3: printf( "hodne spatne"); break;default: printf( "jina chyba"); break;}

switch( ch) {case '0'..'9': x += ch - '0'; break;case 'A'..'F': x += ch - 'A'; break;}

switch( errc) {case 0: b = 0; printf( "OK");case -1: printf( "spatne"); break;}

zapomenutý break syntakticky

OK,ale dělá něco

jiného

interval nelze

celočíselný výraz

ukončení větve

pokud výraz není roven žádné z

konstant

Page 33: Programov ání v  jazyce  C

33

Cyklus – konstrukce while a do-while

while (výraz) příkaz podmínka na začátkudo příkaz while (výraz) ; podmínka na konci

while( a > 1) { fce( a); a = a / 2;}

while( a > 1) a = a / 2;

do { fce( a); a = a / 2;} while( a > 1);

tělo se vždy alespoň jednou

provede

Pozor! cyklus pokračuje pokud je podmínka

platná

Page 34: Programov ání v  jazyce  C

34

for (výraz1 ; výraz2 ; výraz3 ) příkaz

je ekvivalentem

výraz1;while (výraz2 ) { příkaz výraz3 ;}

Cyklus – konstrukce for

i=0;while( i<=9) { fce( i); i=i+1;}

inicializace

for( i=0; i<=9; i=i+1) { fce( i);}

podmínka inkrement

tělo cyklu

FOR I := 0 TO 9 DO FCE(I)

ekvivalent v jiném jazyce

for( init(a); i<9 && a[i] >0; a[i++]=i*2) { fce( i);}

for v C++: obecnější, širší

možnosti použití

jako inicializaci, podmínku i inkrement lze libovolný

výraz

Page 35: Programov ání v  jazyce  C

35

break okamžité ukončení celého cyklu cyklus s podmínkou uprostřed ošetření chybových stavů

continue ukončení (jednoho) běhu těla cyklu

Ukončení cyklu - break, continue

for(;;) { errc = fce(); if( errc < 0) break; jinafce();}

n = 1;while( n<1000) { val = get(); if( val == 0) continue; n = n * val;}

Page 36: Programov ání v  jazyce  C

36

Nepoužívat! .... pokud k tomu není dobrý důvodKdyž už, tak pouze dopředu (skok dozadu = cyklus)Dobrý důvod: výskok z vícenásobně vnořených cyklů

Goto

for( i=0; i<10; i++) { for( j=0; j<10; j++) { if( fnc( i, j) == ERROR) goto konec_obou_cyklu; } }konec_obou_cyklu: dalsi_funkce();

nelze break -ukončil by pouze vnitřní cyklus, vnější cyklus by

pokračoval

labelnávěští

Page 37: Programov ání v  jazyce  C

37

Celočíselné typy

typ 8 bit 16 bit 32 bit

64 bit

char 8 8 8 8

short 8 / 16 16 16 16 / 32

int 16 16 32 32

long 16 32 32 32 / 64

long long

- - 64 64

Základní celočíselné typy jsou znaménkovéPro každý typ existuje unsigned varianta

možné využití unsigned: unsigned char, pole bitů, modulová aritmetika pokud není dobrý důvod, unsigned raději nepoužívat

char short int long long longsize_t, ptrdiff_t, wchar_t

-2GB .. +2GB

Page 38: Programov ání v  jazyce  C

38

Logické a znakové hodnoty a typy

C: Až do r. 1999: neexistuje typ 'boolean'Porovnání a logické operátory jsou celočíselné výrazy

FALSE (nepravda) 0 TRUE (pravda) 1 (libovolná hodnota různá od 0)

důsledek: if( x != 0) if( x) if( x == 0) if( !x)

C++, C99 celočíselný typ bool (C99: _Bool) hodnoty true (=1), false (=0)

char norma neurčuje signed / unsignedkorektní porovnání na nerovnost pouze 0 .. 127'a' < 'ž' ?

signed char -128 .. 127unsigned char 0 .. 255 - 'byte'wchar_t stddef.h: znak rozšířené sady (Unicode)

časté použití:test

(ne)nulovostinapř. ukazatelů

záleží na implementaci

většinou char = signed

40 > 200 !!!

200 -56

Page 39: Programov ání v  jazyce  C

39

enum pohlavi { p_muz, p_zena };

pohlavi p = p_muz;int pp = p_zena;pohlavi q = 0;

enum flags { f1 = 1, f2 = 2, f3 = 4, f4 = 8 };if( x & f1)

...

enum porty { pop3 = 111, ftp = 21, smtp = 80 };

Výčtový typ

C: celočíselné konstanty - OK

C++: samostatný typ - nelze

test bitů

hodnoty doplnípřekladač (od 0)

explicitní hodnoty

Page 40: Programov ání v  jazyce  C

40

'Reálné' typy

float double long double

malá přesnost -

nepoužívat!standard pro

'reálné' výpočty

zvýšená přesnost

double x = 1;double y = x / 3;if( x == 3 * y) printf( "Presne");else printf( "Nepresne");

Pozor!Reálné výpočty

jsou vždy nepřesné

raději nepoužívatpouze pro fyzikální

nebo numerické veličiny

double zustatek = 15.60;

long zustatek_v_halerich = 1560;

pro přesné hodnoty

používejte přesné typy

Page 41: Programov ání v  jazyce  C

41

Celočíselné konverze

Automatické konverze (integral promotions)Výpočty výrazů a předávání parametrů vždy v šíři alespoň int

signed char, unsigned char, signed short signed int unsigned short signed int (pokud je int delší) / unsigned int

Automatické konverze u binárních operací signed int unsigned int signed long unsigned long

float double long double

vždy když je použit menší typ

než int

při nestejných operandech

Page 42: Programov ání v  jazyce  C

42

Přehled operátorů, asociativita a priorita

postfi

x

++ --( )[ ]-> .::

post-in/de-krementacevolání funkceindexpřístup k položce strukturykvalifikace identifikátoru

pre

fix

++ --! ~+ -& *sizeof( )newdelete

pre-in/de-krementacebooleovská a bitová negaceunární +/-reference, dereferenceměření velikostipřetypovánídynamická alokacedynamická dealokace

L .* ->* dereference member-ptru

L * / % multiplikativní operátory

L + - aditivní operátory

L << >>

bitové posuny

L < <=> >=

uspořádání

L == != rovnosti

L & bitové AND

L ^ bitové XOR

L | bitové OR

L && booleovské AND

L || booleovské OR

L ? : podmíněný výraz

P =*= /= %= +=-= &=^= |= <<= >>=

přiřazeníkombinované přiřazení

L , sekvence

Page 43: Programov ání v  jazyce  C

43

Základní aritmetické operátory

+ - * / % podle typu operandů automatická konverze na větší typ % - modulo

x / y 1 x / b 1.666

x % y 2 x % b Error

a / b 1.666 a / y 1.666

a % b Error a % y Error

int x=5, y=3;

double a=5, b=3; modulo je pouze celočíselná

operaceceločíselné dělení

reálné dělení

Page 44: Programov ání v  jazyce  C

44

Bitové a logické operátory

& | ^ ~ - bitové operace AND, OR, XOR, NOT&& || ! - logické operace AND, OR, NOT

5 & 3 1 5 && 3 1

5 | 3 7 5 || 3 1

5 ^ 3 6 5 ^^ 3 Error

5 ^ 15 10

5 & 0 0 5 && 0 0

5 | 0 5 5 || 0 1

neexistuje

5 = 01012

3 = 00112

1 = 00012

7 = 01112

9 = 10012

15 = 11112

10 = 10102

oba op. 0

alespoň jeden

operand 0

alespoň jedenoperand = 0

Page 45: Programov ání v  jazyce  C

45

Zkrácené vyhodnocování, relační operátory

a && b - je-li a=0, b se nevyhodnocuje, výsledek = false (0)a || b - je-li a=1, b se nevyhodnocuje, výsledek = true (1)

< <= >= >== !=

výraz typu int (bool) - výsledek vždy 0 nebo 1 (false, true) porovnávání na (ne)rovnost float/double ! porovnání vs. přiřazení !

int x[10]; // pole 0..9

if( i < 10 && x[i] != 0) y = y / x[i];

test mezí pole předpřístupem k prvku

pole

if( x==y && *x++) ...

Pozor! operátory s vedlejšími efekty se

nemusí provést !

if( x = 1) ...

POZOR!!! Přiřazení!(zde hodnota vždy =

1)

Page 46: Programov ání v  jazyce  C

46

Přiřazení, inkrementace, bitový posun

=+= -= *= /= %= &= |= ^= <<= >>=

kombinované přiřazení a op= b a = a op b

++ -- a++ a = a + 1, výsledkem je stará hodnota a ++a a = a + 1 , výsledkem je nová hodnota a přesněji: a++ (tmp = a, a = a + 1, tmp)

<< >> bitový posun C++ - časté použití pro jiné účely (streams) - přetěžování

i += 2;x[ i+=1] /= 3;

int sum = 0;int i, x[10];

...for( i=0; i<9; sum += x[i++]) ;

pozor - vždy si uvědomit, zda jde

o pre- nebo post- inkrementaci

Page 47: Programov ání v  jazyce  C

47

Podmíněný výraz, sekvence

a ? b : c po vyhodnocení podmínky a se vyhodnotí buď b (je-li a != 0) nebo c (je-li a

== 0)

a , b po úplném vyhodnocení a se vyhodnotí b

x = (y>0 ? y : 0);

x = (tmp = y, y = y + 1, tmp);

ekvivalentx = y++;

ternární operátor

operátor sekvence

('zapomnění')

Page 48: Programov ání v  jazyce  C

48

i = 0;p[ i++] = i++;

Pravidla vyhodnocování

a( b,c)vedlejší efekty parametrů jsou vyhodnoceny před zavoláním fcea && b je-li a nulový, b se nevyhodnocujea || b je-li a nenulový, b se nevyhodnocujea ? b : c po vyhodnocení a se vyhodnotí buď b nebo ca , b po úplném vyhodnocení a se vyhodnotí b

Žádná další pravidla nejsou ostatní operátory jsou vyhodnocovány v libovolném pořadí vedlejší efekty se mohou projevit kdykoliv během výpočtu

možné výsledky:

p[0] = 0; p[1] = 0; p[0] = 1;

Page 49: Programov ání v  jazyce  C

49

Fungující triky vs. chyby

Fungující triky Test ukazatele

while ( p && p->v < v )

p = p->next;

Volání funkce s vedlejším efektem

while ( (c = getchar()) != EOF && c != '\n' );

Kopie řetězce

while ( *a++ = *b++ );

Chyby Vícenásobný výskyt modifikované proměnné

p[ i++] = i++;

Nadbytečné volání funkce s vedlejším efektem

if ( getchar() == 'A' && getchar() == 'B' )

nevím, jestli se provede

Page 50: Programov ání v  jazyce  C

50

Pole

Indexy polí vždy začínají od 0 !Při přístupu se nikdy nekontrolují meze !!!Deklarace: t x[n] - pole x o n prvcích (0..n-1) typu t

Vícerozměrné pole je pole políDeklarace: t x[m][n];Přístup: x[m][n] = a;

int x[5];for( i=1; i <=5; i++) x[i] = i;

0 1 2 3 4 ???

? 1 2 3 4 5

Přepis náhodného místa v paměti !

Nepředvídatelné následky !!

int x[8][8];

for( i=0; i < 8; i++) for( j=0; j < 8; j++) x[ i ] [ j ] = i * j;

Pozor! x[m,n] není prvek dvojrozměrného

poleo souřadnicích m a n

čárka = operátor sekvence

význam:m-prvkové pole

typu(n-prvkové pole

typu t)

Page 51: Programov ání v  jazyce  C

51

Inicializace pole

Při deklaraci pole lze obsah pole inicializovat Nejde o přiřazení, lze pouze při deklaraci Deklarace inicializovaného pole nemusí obsahovat velikost

překladač dopočítá z inicializace u vícerozměrných polí pouze "vnější" rozměr

Při nesouhlasu velkosti pole a počtu inicializátorů velikost > inicializátory: inicializace začátku, obsah zbytku nedefinován velikost < inicializátory: kompilační chyba (Too many initializers)

int cisla[] = { 1, 2, 3, 4 };char* jmena[] = { "Josef", "Karel", "Jana" };int matice[][3] = { { 11, 12, 13 }, { 21, 22, 23 } };

Page 52: Programov ání v  jazyce  C

52

Ukazatele

Co to je proměnná?místo v paměti, typ (-> velikost), hodnota

hodnota se dá číst a většinou i zapisovat

Co to je ukazatel (pointer)?něco, čím si můžu ukazovat na proměnnou(nebo na jiné paměťové místo – pole, položka struktury, dynamická

alokace)

K čemu jsou ukazatele dobré:zpracování řetězců, dynamické datové struktury,předávání parametrů odkazem, práce s buffery, ...

Pro C++ je práce s ukazateli typická

1někde bydlí

je nějak velká (typ)

má hodnot

u

Page 53: Programov ání v  jazyce  C

53

Ukazatele

Deklarace:t x – proměnná x typu tt *p - ukazatel p na typ t

Operátor reference: p = &xOperátor dereference: x = *p

Neinicializovaný ukazatel vs. nulový ukazatel C: #define NULL 0 C++: 0

17x:

p:

Page 54: Programov ání v  jazyce  C

54

Ukazatele - příklad

int x = 1, y = 3;int * px, * py;*px = 5;py = NULL; *py = 7;if( ! py) etwas();px = &x; py = &y;(*py)++;px = py; y = x;py = &x; *py = 9;

přepsání náhodného místa v

paměti

1x: :px

3y: :py

?

? 5

jaký zde bude obsah x a y?

Page 55: Programov ání v  jazyce  C

55

Ukazatele - příklad

int x = 1, y = 3;int * px, * py;*px = 5;py = NULL; *py = 7;if( ! py) etwas();px = &x; py = &y;(*py)++;px = py; y = x;py = &x; *py = 9;

typicky 'segmentation fault'váš program bude ukončen

pro pokus o porušení ochrany paměti

1x: :px

3y: :py

0: 7

umožní test

Page 56: Programov ání v  jazyce  C

56

Ukazatele - příklad

int x = 1, y = 3;int * px, * py;*px = 5;py = NULL; *py = 7;if( ! py) etwas();px = &x; py = &y;(*py)++;px = py; y = x;py = &x; *py = 9;

přístup k hodnotě proměnné přes

ukazatel

1x: :px

4y: :pyPozor na prioritu!

*py++ *(py++)

1x: :px

3y: :py

Page 57: Programov ání v  jazyce  C

57

Ukazatele - příklad

int x = 1, y = 3;int * px, * py;*px = 5;py = NULL; *py = 7;if( ! py) etwas();px = &x; py = &y;(*py)++;px = py; y = x;py = &x; *py = 9;

1x: :px

1y: :py

9x: :px

1y: :pyjaký zde bude obsah x a y?

Page 58: Programov ání v  jazyce  C

58

Pole a ukazatele, aritmetika ukazatelů

int a[5];int *p;

a[2] = 20;p = &a[2];

a[0] = *p - 15;p++;*p = 30;

0 1 2 3 4

? ? 20 ? ?

5 ? 20 30 ?

p

p

reference na prvek pole

inkrementace ukazatele

posun na daší prvek

a

Page 59: Programov ání v  jazyce  C

59

Pole a ukazatele, aritmetika ukazatelů

p = &a[1];*(p+3) = 40;

Operátor []

p[i] *(p+i)

&p[i] p+i

a &a[0]

5 ? 20 30 40

p

přičtení čísla k ukazateli posun o n prvků

identifikátor pole je ukazatel na svůj nultý

prvek

indexování pole (ukazatele) je jen jiný zápis přístupu přes

ukazatel

Automatické konverze pole-ukazatelJe-li výraz typu pole na místě, kde typ pole nemůže být, automaticky se konvertuje na ukazatel na nultý prvek tohoto pole.

Pole nelze přiřazovat ani předávat hodnotou (ukazatel na nultý prvek)

p = a je ekvivalentní p = &a[0]

Page 60: Programov ání v  jazyce  C

60

Pole a ukazatele, aritmetika ukazatelů

int a[5];int *p;

identifikátor pole je konstantní nelze do něj přiřazovat

0 10 20 30 40

p = &a[0];p = a;*p = a[1];*(p+2) = a[2] – 1;p = a + 2;p[1] = *(a+1);a[3] = p[2];*(a+2) = p[-1];3[a] = 2[p];

a[4] = p + 1;p = a[0];p[1] = a;

a = p + 2;

nekompatibilní typynestejná úroveň

indirekce

p[i] *(p+i) *(i+p) i[p]

Page 61: Programov ání v  jazyce  C

61

Řetězce

Jazyk C++ nezná pojem řetězec (!) – konvence, knihovnyŘetězec je pole znaků (char) zakončené nulou

"Ahoj"

X proměnná'X' znaková konstanta - celočíselná hodnota"X" řetězec - ukazatel

'A' 'h' 'o' 'j' '\0'

Každý řetězec musí být vždy

ukončen nulou

'A' 'h' 'o' 'j' '\0'

vždy myslet na koncovou nulu !

pozor na uvozovky a apostrofy !

char buffer[4];strcpy( buffer, "Ahoj");

'\0' = 0

kód znaku v použitém kódování

(ASCII, CP1250, ISO08859-2, EBCDIC, ...)když chcete říct mezera, napište

mezeru (' ')ať vás ani nenapadne napsat 32

přestože to na VAŠEM počítačí funguje

Page 62: Programov ání v  jazyce  C

62

'Řetězcové proměnné'

char s1[] = "Uno";

const char *s2 = "Due";

'U' 'n' 'o' '\0'

'D' 'u' 'e' '\0'

s1:

s2:

Inicializovaná proměnnátypu ukazatel

s2++ se přesune na další znak

Inicializované pole(konstantní ukazatel)

s1++ nelze!

anonymní globální proměnná

const char[]

Page 63: Programov ání v  jazyce  C

63

Řetězce – knihovní funkce, délka řetězce

v C neexistují 'řetězcové operace' (C++: třída string) přiřazení, zřetězení, porovnání, podřetězec, ... vše standardní knihovní funkce

#include <string.h>

int strlen( const char* s);

A h o j \0 ? ? ?pole:

počet znaků(bez koncové

nuly)

char pole[8] = "Ahoj";x = strlen( pole); // 4

skutečný počet znaků (4)

nikoliv velikost pole

deklarace řetězcových funkcí

inicializované pole typu char

Page 64: Programov ání v  jazyce  C

64

Délka řetězce – různé způsoby implementace

int i = 0;while ( *s != '\0') { i++; s++;}return i;

int strlen ( const char* s){ int i = 0; while ( s[i] != '\0') { i++; } return i;}

char *p = s;while (*p++) ;return p-s-1;

for( i=0; *s != '\0'; i++) s++;

for( i=0; *s != '\0'; i++, s++) ;

int i=0;while ( *s++ != '\0') i++;

int i=0;while ( *s++) i++;

přístup přes index

přístup přes ukazatel

podmínka for cyklu může být

libovolná

více inkrementací prázdné tělo

nezapomenout na ';' !!

složitější podmínka:test nenulovostiinkrementace

ukazatele

while(a!=0) while(a)

podmínka je splněnapokud je nenulová

rozdíl ukazatelů = počet prvků mezi

nimi pozor na ± 1 !

Page 65: Programov ání v  jazyce  C

65

Řetězce - kopírování

char* strcpy( char* d, const char* s);

zkopíruje obsah sdo místa začínajího od

dchar buf[8];char pozdrav[] = "Ahoj";strcpy( buf, pozdrav);

A h o j \0pozdrav

A h o j \0 ? ? ?buf

kopíruje pouze do koncové '\0'

Page 66: Programov ání v  jazyce  C

66

Řetězce – chyby při kopírování

D o b r y d e n \0pozdrav

buf

char buf[6];char pozdrav[] = "Dobry den";strcpy( buf, pozdrav);

D o b r y d e n \0

vždy pozor na dostatek místa

funkce nic nekontroluje !!!váš program provedl...

char *ptr;char pozdrav[] = "Ahoj";strcpy( ptr, pozdrav);

kopírování na neinicializovaný ukazatel !!!

váš program provedl...

A h o j \0pozdrav

ptr?

A h o j \0

ptr neinicializovaný !!!

Page 67: Programov ání v  jazyce  C

67

Řetězce – zřetězení, vyhledávání

char* strcat( char* d, const char* s); připojí s za dchar* strchr( const char* s1, int c); vyhledá první pozici c v s1char* strstr( const char* s1, const char* s2); vyhledá podřetězec s2 v s1

char buf[10];char* bp;strcpy( buf, "Ahoj");strcat( buf, "Babi");bp = strstr( buf, "oj");

A h o j \0

? ? ? ? ?po strcpy

A h o j B a b i \0

?po strcat

buf

bp

A h o j B a b i \0

?pozor na dostatek

místa !

Page 68: Programov ání v  jazyce  C

68

Řetězce – porovnávání a další funkce

int strcmp( const char* s1, const char* s2);s1 < s2 -1s1 = s2 0s1 > s2 +1

lexikografické uspořádání (jako ve slovníku)

další řetězcové funkce:strncat, strncmp, strncpy strrchr Find last occurrence of given character in string strpbrk Find first occurrence of character from one string in another string strspn Find first substring from one string in another string strtok Find next token in string sprintf Write formatted data to a string

co znamená 's1 < s2'? A B C E

= = =

A B C D E

výsledek podle prvního rozdílného

znaku

Page 69: Programov ání v  jazyce  C

69

Funkce printf

int printf( const char *format [, argument]... ) Vytiskne na standardní výstup text definovaný formátovacím řetězcem Formátovací řetězec určuje počet a typy dalších parametrů (symbolem %)

Výjimka z pravidla, že funkce v C má přesně daný počet a typy parametrů. Kompilátor nemá možnost ověřit zda parametry jsou správné časté pády

programu Vrací počet skutečně vytisknutých znaků

#include <stdio.h>double r = 2.6;int c = 65;char * buf = "Ahoj";

printf ("Soucet cisel %d + %.2f = %.2f \n", 7, r, r + 7);

printf ("Retezec %s zacina na %c \n", buf, buf[0]);

printf ("ASCII kód znaku %c je %i \n", c, c);

%s – řetězec%d, %i – celé číslo%c – znak%f – reálné číslo%08d – zarovná na 8 míst, doplní 0%5.2f – zarovná na 5 míst, 2 desetinná místa\n – odřádkuje\t – tabulátor\\ – \ (cesta k souborům)

printf ("%s", r);

printf ("%i + %i = %i", c, c);

Page 70: Programov ání v  jazyce  C

70

Parametry příkazové řádky

C:\> myprog.exe -n -w a.txt b.txt

0

m y p r o g . e x e \0

- n \0

- w \0

a . t x t \0

b . t x t \0

argv

5argc

int main( int argc, char** argv)

pole řetězců(ukazatelů na char)

Počet parametrůvčetně názvu programu !

= počet ukazatelů v argv

Page 71: Programov ání v  jazyce  C

71

Zpracování příkazové řádky – výpis parametrů

int main( int argc, char** argv){ while( *argv) { printf( "%s\n", *argv); argv++; }}

C:\> myprog.exe -n -w a.txt b.txt

myprog.exe-n-wa.txtb.txt

výstup řetězce a

odřádkováníposun na další

parametr

Page 72: Programov ání v  jazyce  C

72

Zpracování příkazové řádky

int main( int argc, char** argv){ while( *argv) { printf( "%s\n", *argv); argv++; }}

m y p r o g . e x e \0

- n \0

- w \0

a . t x t \0

b . t x t \0

argv

0

argvtyp:

char**

**argv argv[0][0]

typ: char

argv[4][1]

*argv argv[0]

typ: char*

argv[4]

Page 73: Programov ání v  jazyce  C

73

Zpracování příkazové řádky

int main( int argc, char** argv){ while( *argv) { printf( "%s\n", *argv); argv++; }}

m y p r o g . e x e \0

- n \0

- w \0

a . t x t \0

b . t x t \0

argv

0

argv++ **argv

Page 74: Programov ání v  jazyce  C

74

Zpracování příkazové řádky

int main( int argc, char** argv){ while( *argv) { printf( "%s\n", *argv); argv++; }}

m y p r o g . e x e \0

- n \0

- w \0

a . t x t \0

b . t x t \0

argv

0

*argv == 0

Page 75: Programov ání v  jazyce  C

75

Zpracování příkazové řádky

int main( int argc, char** argv){ int n=0, w=0; while( *++argv && **argv=='-') { switch( argv[0][1]) { case 'n': n = 1; break; case 'w': w = 1; break; default: error(); } } if( !argv[0] || !argv[1]) error(); doit( argv[0], argv[1], n, w); return 0;}

options

usage: myprog [-n] [-w] fileA fileB

nastavení přepínače

zbývající parametry

výkonná funkce

p r g . e x e \0

- n \0

- w \0

a . t x t \0

b . t x t \0

0

argv

Page 76: Programov ání v  jazyce  C

76

Dynamická alokace paměti

C: standardní knihovny <malloc.h> void* malloc( int size); void free( void* p);

C++: součást jazyka (podrobně později)

new T new T[ n] delete p delete[] p

char* s;s = malloc( 20);if( ! s) error();strcpy( s, "ahoj");*s = 'X';

s:

X h o j \0

C++ nutnost přetypování

s = (char*) malloc( 20);lépe new

vždy ověřit !!!váš program

provedl...

int * pole;pole = malloc(20 * sizeof(int));

Velikost datového typusizeof(char) = 1 vždy

Page 77: Programov ání v  jazyce  C

77

Velikost pole určena za běhu programu

int main( int argc, char** argv){ char* buf; ... buf = malloc( strlen(argv[1]) + strlen(argv[2]) + 1))); if( ! buf) error(); strcpy( buf, argv[1]); strcat( buf, argv[2]);

spočítá potřebnou velikost

ze vstupních parametrů

pozor na koncovou '\0'

Page 78: Programov ání v  jazyce  C

78

Organizace paměti procesu

Kódový segment Kód programu

Datový segment Globální proměnné

Heap Dynamicky alokovaná data

Zásobník Lokální proměnné a parametry

funkcí

IP

R0R1...

SP

Page 79: Programov ání v  jazyce  C

79

Organizace paměti procesu – kódový segment

Kódový segment Připraven kompilátorem

součást spustitelného souboru

Kód uživatelských i knihovních funkcí

Obvykle chráněn proti zápisu Datový segment Heap Zásobník

IP

R0R1...

SP

int fce( void) { ... }

{ int (*fp)( void); fp = fce; ...

Page 80: Programov ání v  jazyce  C

80

Organizace paměti procesu – datový segment

Kódový segment Datový segment

Připraven kompilátorem součást spustitelného souboru

Explicitně nebo implicitně (nulami) inicializované globální proměnné

Řetězcové konstanty Data knihoven

Heap Zásobník

IP

R0R1...

SP

int bigpole[ 1000];

{ int* p = bigpole; char* s = "ahoj"; ...

Page 81: Programov ání v  jazyce  C

81

Organizace paměti procesu - heap

Kódový segment Datový segment Heap

Vytvářen startovacím modulem knihoven

Neinicializovaná dynamicky alokovaná data

malloc/free ( C++: new/delete ) Obsazené bloky různé velikosti

+ seznam volných bloků Zásobník

IP

R0R1...

SP

{ char* s; s = malloc( 256); ...

Page 82: Programov ání v  jazyce  C

82

Organizace paměti procesu - zásobník

Kódový segment Datový segment Heap Zásobník

Připraven operačním systémem Lokální proměnné Pomocné proměnné generované

kompilátorem Návratové adresy Aktivační záznamy funkcí

IP

R0R1...

SP

{ char pole[100]; char s[] = "Ahoj"; int x = 1 + 2 * 3; ...

Page 83: Programov ání v  jazyce  C

83

Statické proměnné

static int x;

int fce( int a){ static int y = 0; return y += a;}

globální proměnná neviditelná z jiných

modulů

de facto globální (!) proměnná neviditelná z

jiných funkcí

inicializace:C: před vstupem do mainC++: před prvním průchodem

C++: lepší řešení - namespace

C++: raději skrýt do třídy

Page 84: Programov ání v  jazyce  C

84

Organizace paměti procesu – příklad

const int max = 100;char buf[max];

char* prefix( char* s){ static int n = 0; char* p = malloc( strlen( s) + 2); *p = '#'; strcpy( p + 1, s); return p;}

int main( int argc, char** argv){ char* p; strcpy( buf, argv[ argc – 1]); p = prefix( buf); p = prefix( p); ....}

co je v kterém segmentu?

Page 85: Programov ání v  jazyce  C

85

Struktury

struct osoba {char jmeno[20];char prijemni[30];int rok_narozeni;int pohlavi;

};

osoba os, *po, zam[20];osoba beda = { "Béda", "Trávníček", 1980, p_muz };

strcpy( os.jmeno, "Venca");zam[3].rok_narozeni = 1968;po = &zam[3]; po->pohlavi = p_muz;

definice struktury

položky struktury

struktura, ukazatel na strukturu, pole

struktur

přístup k položkám(*x).y x->y

definice proměnné typu struktura s

inicializací

Page 86: Programov ání v  jazyce  C

86

Typové kostrukce - přehled

A x[ n] pole n prvků typu A, n je konstantní výraz

A x[] pole neznámého počtu prvků typu A (pouze v některých kontextech)

A * x ukazatel na typ A

void * x ukazatel na neurčený typ *x ++x nelze

A const * xconst A * x

ukazatel na konstantní hodnotu typu A ++x lze ++*x nelze

A * const x konstantní ukazatel na typ A ++x nelze ++*x lze

A & x C++: reference na typ A

A const & xconst A & x

C++: reference na konstantní hodnotu typu A

A x() funkce vracející typ A - C: bez určení parametrů , C++: bez parametrů

A x( par) funkce s určenými parametry

A x( void) funkce bez parametrů

void x( par) funkce bez návratové hodnoty (procedura)

Page 87: Programov ání v  jazyce  C

87

Kombinace typových kostrukcí

A * x[10] pole ukazatelů

A (* x)[10] ukazatel na pole

A * x() funkce vracející ukazatel

A (* x)() ukazatel na funkci

A x[10]() pole funkcí - zakázáno

A (* x[10])() pole ukazatelů na funkci

A x()[10] funkce vracející pole - zakázáno

A (* x())[10] funkce vracející ukazatel na pole

čtení deklarací: od identifikátoru doprava,

až to nepůjde, tak doleva

typicky se nepoužívápole = ukazatel na 1.

prvek

Page 88: Programov ání v  jazyce  C

88

int*(*pf[10])(void);

int*(*maso(int*(*p1)(void),int*(*p2)(void)))(void);

Kombinace typových kostrukcí - příklad

co to je za maso ???

Page 89: Programov ání v  jazyce  C

89

int*(*pf[10])(void);

int*(*maso(int*(*p1)(void),int*(*p2)(void)))(void);

typedef int* fce( void);

fce * pf [10];

fce * maso( fce* p1, fce* p2);

Kombinace typových kostrukcí - typedef

použitím typedef se může výrazně

zpřehlednit kód

Page 90: Programov ání v  jazyce  C

90

Souborový vstup a výstup

struktura definovaná

v <stdio.h>

Neznámý obsah

Pro knihovní funkce

FILE *

FILE

deskriptor souboru -deklaruje

programátor

Otevření souboru: kontrola existence a práv vytvoření vnitřních knihovních struktur asociace s otevřeným souborem předání deskriptoru souboru (FILE*)

soubor(na disku)

OS

Page 91: Programov ání v  jazyce  C

91

#include <stdio.h>

FILE* fp;int c;

if( !(fp = fopen("c:\\f.txt", "r")))error();

while( (c = getc( fp)) != EOF)putchar( c);

fclose( fp);

Práce se soubory

typ 'soubor'(ukazatel na strukturu)

otevření

souboru

čtení ze soubor

u

zavření souboru

pozor na '\\' !!!

Page 92: Programov ání v  jazyce  C

92

Otevření souboru

FILE* fopen( const char* fname, const char* mode);

r open file for readingw truncate to zero length or create file for writinga append; open or create file for writing at end-of-filer+ open file for update (reading and writing)w+ truncate to zero length or create file for updatea+ append; open or create f. for upd., writing at end-of-file

rb binary file... mod

esoubor ex.

soubor neex.

seek

r R Error 0

w Del, W W 0

a W W End

r+ R/W Error 0

w+ Del, R/W R/W 0

a+ R/W R/W End

+: vždy čtení i zápis

a: otevřít na konci

r: soubor musí existovat

w: soubor se smaže

Page 93: Programov ání v  jazyce  C

93

Textové vs. binární soubory

Textový soubor konverze konců řádek ('\n') na platformově závislou vnější reprezentaci typicky 0x0D 0x0A (Win) nebo 0x0A (Unix) konverze je automatická, programátor se o to nemusí starat vhodné pro ukládání lidsky čitelných dat getc/putc, fgets/fputs, fprintf, ... chování fseek/ftell na '\n' nedefinován - nepoužívat

Binární soubor žádné konverze se neprovádí v souboru je přesný binární obraz zapisovaných dat vhodné pro ukládání vnitřních datových struktur lidsky přímo nečitelné typicky fread/fwrite, lze i getc/putc (přístup po bajtech) fseek/ftell OK

Page 94: Programov ání v  jazyce  C

94

Funkce pro práci se soubory

FILE* fopen( const char* fname, const char* mode);int fclose( FILE* fp);int fprintf( FILE* fp, const char* format, ...);int getc( FILE* fp);int putc( int c, FILE* fp);char* fgets( char* buffer, int limit, FILE* fp);int fputs( const char* buffer, FILE* fp);

int fread( void* ptr, int size, int n, FILE* fp);int fwrite( const void* ptr, int size, int n, FILE* fp);long ftell( FILE* fp);int fseek( FILE* fp, long offset, int whence);

whence: SEEK_SET, SEEK_CUR, SEEK_END

Zjištění velikosti souboru:

fseek( fp, 0, SEEK_END);

size = ftell( fp);

Page 95: Programov ání v  jazyce  C

95

Souborový vs. standardní v/v

funkce pro práci se standardním vstupem/výstupem int getchar( void); int putchar( int c); int printf( const char* format, ...);

char* gets( char* buffer);

standardní vstup/výstup FILE* stand. otevřený na čtení/zápis před vstupem do main

FILE *stdin;FILE *stdout;

getchar() getc(stdin)putchar(c) putc(c, stdout)

FILE* fp = stdout;if( ...) fp = fopen( "...", "r");c = getc( fp);

jednotný zápisna std výstup nebo

do souboru

Nepoužívat!Nelze ohlídat přetečení

bufferu

všechny souborové

funkce lze použíti pro std. v/v

Page 96: Programov ání v  jazyce  C

96

Základní knihovní (neobjektové) funkce

<string.h> <cstring>strlen, strcmp, strcpy, strncpy, strcat, strchr, strstr,memset, memcmp, memcpy, memchr<stdio.h> <cstdio>getchar, putchar, fopen, fclose, getc, putc, fgets, fputs, fread, fwrite, ftell, fseek, printf, fprintf, vfprintf, fflush, ungetcFILE, stdin, stdout, EOF, SEEK_SET, ...<stdlib.h> <cstdlib>malloc, free, atoi, atof, strtol, qsort, rand, exit<ctype.h> <cctype>isalpha, isdigit, isxdigit, isalnum, isspace, ispunct, iscntrl, islower, isupper, tolower, toupper<math.h> <cmath>abs, floor, sin, sqrt, exp, exp, log, ...<time.h> <ctime>time, gmtime, strftime, asctime, clock, ...

... a mnoho mnoho dalších

Page 97: Programov ání v  jazyce  C

97

Typy znaků

<ctype.h> <cctype> Funkce vrací 0 nebo 1, podle toho zda zadaný znak je daného typu Parametrem funkce je jednotlivý ZNAK, ne celý řetězec

isdigit – číslice (0, ..., 9)isxdigit – hexadecimální číslice (0, ..., 9, a, ..., f, A, ..., F)isalnum – číslice nebo písmeno (0, ..., 9, a, ..., z, A, ..., Z)isspace – bílé znaky (mezera, tabulátor, konec řádku, ...)ispunct – interpunkční znaménka (?, !, ., ...) iscntrl – netisknutelné řídící znakyisalpha – písmeno (a, ..., z, A, ..., Z)islower – malé písmeno (a, ..., z)isupper – velké písmeno (A, ..., Z)tolower – k zadanému písmenu vrací příslušné malé písmenotoupper – k zadanému písmenu vrací příslušné velké písmeno

Problém v C: české znaky, ale i jiné diaktické znaky

Page 98: Programov ání v  jazyce  C

98

Funkce qsort

#include <stdio.h>#include <stdlib.h>#include <string.h>

int compare( const void *arg1, const void *arg2 ){ return _stricmp( * ( char** ) arg1, * ( char** ) arg2 );}

void main( int argc, char **argv ){ int i; argv++; argc--; qsort( (void *)argv, (size_t)argc, sizeof( char * ), compare );

for( i = 0; i < argc; ++i ) printf( "%s ", argv[i] ); printf( "\n" );}

Uživatelsky napsaná třídící funkce. Návratové

hodnoty 0, < 0, a > 0.

Parametry: pole k setřídění, počet prvků pole, velikost 1 prvku, porovánací funkce

Ignore case

Page 99: Programov ání v  jazyce  C

99

Direktivy preprocesoru

#include <stdio.h>#include <cstdio>#include <iostream>#include "mymodul.h"

#define KZR#define KZR 17#define KZR( pzr) ((pzr) * 2)#undef

#ifdef#ifndef#if#else#endif###

knihovní headery – C, C dle nových konvencí, C++

uživatelské headery

definice symbolu – viz slajd Spojování modulů - #ifndef

definice makra, lépe const int kzr = 17;

definice parametrického makraraději vůbec nepoužívat, lépe inline

funkcetest na (ne)definovanost symbolu

obrana před vícenásobným #includeviz slajd Spojování modulů - #ifndef

test konstantního výrazu - #if sizeof( int) == 4

'ouvozovkování' - #abc "abc"

spojení identifikátorů - a##b ab

Page 100: Programov ání v  jazyce  C

100

x.c

double A() { return B( 7);}

Spojování modulů – problém

error:Undefined 'B'

y.c

double B() { return 3.14;

}

Page 101: Programov ání v  jazyce  C

101

x.cdouble B();double A() { return B();}

Spojování modulů – externí deklarace

externí deklarace

y.c

double B() { return 3.14;

}

Page 102: Programov ání v  jazyce  C

102

Spojování modulů – nekonzistence

C: nedefinované chování

C++: linker error

x.cdouble B();double A() { return B();}

y.c

int B( int q) { return q+1; }

x.obj

import Bexport A

y.obj

export Bapp.exe

nekonzistence funkce B

(počet a typy parametrů, návratová hodnota)

Page 103: Programov ání v  jazyce  C

103

Spojování modulů – header

hlavičkový soubor (header)

x.c#include "y.h"double A() { return B( 7);}

y.c

int B( int q) { return q+1; }

y.h

int B( int q);

int B( int q);double A() { return B( 7);}

preprocesor

Page 104: Programov ání v  jazyce  C

104

Spojování modulů – nekonzistence

nekonzistence

x.c#include "y.h"double A() { return B( 7);}

y.c

double B() { return 3.14;

}

y.h

int B( int q);

int B( int q);double A() { return B( 7);}

Page 105: Programov ání v  jazyce  C

105

Spojování modulů – řešení

x.c#include "y.h"double A() { return B( 7);}

y.c#include "y.h"double B() { return 3.14;

}

y.h

int B( int q);

int B( int q);double A() { return B( 7);}

int B( int q);double B() { return 3.14;

}

error:Redefinition of 'B'

Page 106: Programov ání v  jazyce  C

106

y.obj

export c

Spojování modulů – duplicitní data

x.c#include "y.h"double A() {}

y.c#include "y.h"int c;

y.h

int c;

int c;double A() {}

int c;int c;

x.obj

export c export A

linker error: Duplicate symbol 'c'

Page 107: Programov ání v  jazyce  C

107

y.obj

export c

Deklarace vs. definice

x.c#include "y.h"double A() {}

y.c#include "y.h"int c;

y.h

extern int c;

extern int c;double A() {}

extern int c;int c;

x.objimport c export A

Deklarace

Definice

Deklarace

Definice

Page 108: Programov ání v  jazyce  C

108

Spojování modulů - typy

x.c#include "y.h"double A() { return C; }

y.c#include "y.h"

enum T C;

y.henum T { P, Q};extern enum T C;

enum T { P, Q};extern enum T C;double A() { return C; }

enum T { P, Q};extern enum T C;

enum T C;

Příklad definice nového typuteď není nutné chápat přesný význam Deklarace proměnné tohoto typu

Page 109: Programov ání v  jazyce  C

109

Spojování modulů - duplicita typů

x.c#include "y.h"#include "z.h"double A() { return C+D; }

t.henum T { P, Q};

enum T { P, Q};extern enum T C;

enum T { P, Q};extern enum T D;

double A() { return C + D; }

y.h#include "t.h"extern enum T C;

z.h#include "t.h"extern enum T D;

error:Type redefinition: 'T'

Přes y.h a z.hje t.h vložen dvakrát

Page 110: Programov ání v  jazyce  C

110

Spojování modulů - #ifndef

x.c#include "y.h"#include "z.h"double A() { return C+D; }

t.h#ifndef _T_H#define _T_Henum T { P, Q};#endif

#ifndef _T_H#define _T_Henum T { P, Q};#endifextern enum T C;

#ifndef _T_H#define _T_Henum T { P, Q};#endifextern enum T D;

y.h#include "t.h"extern enum T C;

z.h#include "t.h"extern enum T D;

symbol již definován

nepřekládá se

není-li symbol definován ...

definice nového symbolu (makra)

Page 111: Programov ání v  jazyce  C

111

Programování není zápis algoritmů

Běhové prostředí programu Vazba programu na operační systém Přenositelnost mezi platformami Typické chyby a ochrana proti nim Ladění programů debuggerem a bez debuggeru Udržovatelné programy, kultura programování

Page 112: Programov ání v  jazyce  C

112

Vazba programu na operační systém

Proces je izolován od ostatních procesů a jádra OS Virtuální adresový prostor a/nebo ochrana paměti Přímá komunikace s I/O zařízeními není možná Přímá komunikace s jinými procesy by byla možná technikou sdílené paměti

Není ovšem všude dostupná a standardizována Použití efektivní ale obtížné a nebezpečné

Veškerá komunikace přes systémová volání Systémové volání zajišťuje:

Přechod z uživatelského režimu do privilegovaného a zpět Možnost suspendování procesu uvnitř systémového volání

Konkrétní technika systémového volání závisí na HW a OS Softwarové přerušení, brány, speciální volání, falešné výjimky Obvykle není možné volání přímo z C/C++ Relativně pomalé (změna kontextu, přeplánování)

Množina systémových volání je definována OS Může být přímo zpřístupněna knihovnou (Unix, "io.h") Nemusí být zveřejněna (Microsoft)

Page 113: Programov ání v  jazyce  C

113

Zveřejněné rozhraní operačního systému

"C-API"Zpřístupněno knihovnami pro C (výjimečně C++)

Nejtypičtějsí část je standardizována Většina je závislá na OS

Knihovní funkce obvykle provádějí více než jedno systémové volání Některé knihovny mohou zcela změnit původní logiku systémových volání

Soubory: Buffering, překlad znakových sad, statefull/stateless Spouštění procesů: spawn = fork + exec

Vnitřek knihovních funkcí může záviset na verzi OS Připojovány jako DLL v okamžiku startu procesu (Microsoft)

Pozor na různé verze !!

Page 114: Programov ání v  jazyce  C

114

Standardizovaná rozhraní OS

stdio.h - souborový vstup a výstup Přístup "s ukazovátkem" Sjednocení přístupu k souborům a rourám

stdin, stdout, stderr Buffering - snížení počtu systémových volání

Následky při pádu programu - fflush Textový/binární mód

Překlad do jednotné formy - oddělovač řádků "\n" Neřeší adresářové služby

signal.h, stdlib.h - řízení procesu Vyvolání/příjem signálu (podle Unixového vzoru) Ukončení procesu system( "winword my.doc")

Page 115: Programov ání v  jazyce  C

115

Vlákna (threads)

Pro realizaci serverů i některých GUI aplikací Je-li třeba souběžně vykonávat více činností Nebo čekat na více událostí různých druhů

Proces může mít více vláken (threads) Všechna vlákna žijí uvnitř společného adresového prostoru Každé vlákno má vlastní zásobník (a tedy jiný SP) První vlákno je spuštěno při spuštění procesu Další vlákna vznikají na pokyn již existujících vláken Vlákna běží kvazi-paralelně, na multiprocesorech paralelně (!)

Všechny moderní OS vlákna podporují Způsoby implementace se mohou výrazně lišit Lze je též implementovat na úrovni knihoven bez vědomí OS

Norma C ani C++ o vláknech nehovoří Neexistuje přenositelný způsob práce s vlákny Existuje poměrně jednotná terminologie převzatá z teorie OS Existují pokusy o unifikaci prostřednictvím nestandardních knihoven

Programování s vlákny je obtížnější Nešikovná vzájemná komunikace vláken může zdržovat i zablokovat Využití vláken na multiprocesorech vyžaduje zvláštní opatrnost - Pozor na externí

knihovny!

Page 116: Programov ání v  jazyce  C

116

Odlišnosti mezi platformami

Vlastnosti hardware Velikost adresového prostoru a velikostí ukazatelů Pořadí ukládání vícebajtových hodnot (little/big endian) Dostupné formáty celých a reálných čísel

Vlastnosti operačního systému Znaková sadou (ASCII/EBCDIC, Win/ISO), oddělovače řádků Konvence jmen souborů (oddělovače, povolené znaky, délka) Další vlastnosti souborového systému (sémantika delete, links, přístupová práva) Základní služby a konvence OS (environment, registry) Konvence (/usr/bin, .exe, $HOME)

Vlastnosti překladače Volba velikosti základních aritmetických typů Způsob zarovnání položek struktur Rozpoznávaná pod-/nad-množinou jazyka Chyby v diagnostice a generovaném kódu

Vlastnosti knihoven Dostupnost, pojmenování a sémantika funkcí

Page 117: Programov ání v  jazyce  C

117

Přenositelnost mezi platformami

Zákaz konstrukcí závislých na vlastnostech hardware a překladače

Užívání základních typů prostředníctvím typedef

typedef unsigned long UINT32; Opatrné užívání pokročilých konstrukcí

(member-pointers, templates) Přednostní používání funkcí

definovaných normou jazyka Nelze-li jinak, užívání direktiv #ifdef

#ifdef _MSC_VER // Microsoft typedef __int64 INT64; const char delimiter = '\\'; #else typedef long long INT64; #ifdef UNIX const char delimiter = '/'; #else const char delimiter = '\\'; #endif#endif

int x; char * p = (char *)&x;struct { char a; int b; } S; fwrite( &S, 1, sizeof( S), fp);

Ideál: Program přenositelný bez úpravy zdrojového textu

Page 118: Programov ání v  jazyce  C

118

Ladění programů debuggerem

Spustit program v ladicím režimu Některé zvládnou i připojení k již běžícímu procesu (JIT Debugging) Ladicí režim nemusí být (a typicky není) pro laděný program identický s

normálním Většina funkcí debuggeru je možná pouze pro programy přeložené v

ladicím nastavení překladače (bez optimalizací) Chybný program se může chovat při ladění jinak než finální verze

Krokovat a spouštět program Odchytit chybující program a zobrazit stav těsně před chybou Nedestruktivně zastavit běžící program Nastavovat breakpointy do kódu

Mohou být podmíněné Nastavovat breakpointy na data (změna či splnění podmínky)

Některé typy mohou o několik řádů zpomalit běh programu Zobrazovat zásobník volání Zobrazovat lokální i globální proměnné Zobrazovat paměť laděného procesu

Page 119: Programov ání v  jazyce  C

119

Ladění programů bez debuggeru

Ladicí 'tisky' Co tisknout Kdy a kde tisknout Jak tisknout ('monitor', soubor, databáze, ...)

Automatické testování Testovací skripty Sady testovacích dat

Lokalizace chyby Minimalizace zdrojového textu, kde se chyba vyskytuje Prevence proti zavlečeným chybám

Ladicí implementace alokačních funkcí Obložit každý alokovaný blok prostorem vyplněným značkami Při dealokaci zkontrolovat neporušenost značek a změnit je

Page 120: Programov ání v  jazyce  C

120

Bezpečné programování

Zapnout všechna varování, která je schopen kompilátor vydat Upravit program do podoby, která nezpůsobí žádné varování V odůvodněných případech lze varování vypnout pomocí #pragma

Dodržovat pravidla pro přenositelné a vícevláknové programy A to i když přenositelnost ani vícevláknovost zdánlivě nemá smysl

Minimum globálních proměnných, pokud možno pouze konstantní Procedura smí číst či měnit pouze objekty, které jsou přímo či nepřímo určeny jejími

parametry Důsledné užívání ochranných prostředků kompilátoru

const, private, ... Důsledná chybová diagnostika

Test úspěšnosti každého malloc, fopen, ... Testy proti interním chybám a špatným parametrům Ochrana proti užívání odalokovaných bloků Ochrana proti přetečením polí

Všechny funkce manipulující s polem dostávají velikost pole jako parametr Žádné strcat, gets a podobné nebezpečné funkce

Největší nepřítel je chyba, která není vždy a ihned smrtelná Dereference nulového ukazatele se pozná ihned Dereference neinicializovaného ukazatele způsobí pád později

void f( int* p){ assert( p); /*...*/ }

free(p); p=0;

Page 121: Programov ání v  jazyce  C

121

Udržovatelné zdrojové texty Logické rozdělení do modulů a hlavičkových souborů

na nižší úrovni datové struktury a funkce, třídy

Jasné oddělení rozhraní od implementace Oddělení obsluhy uživatelského rozhraní od vlastní logiky aplikace Minimum globálních proměnných

ideálně žádné, příp. třída (struktura) app

Komentáře, zejména k rozhraním Indentace, omezená délka řádek Pojmenovávací konvence, logicky zvolené a dlouhé identifikátory

Buďto my_big_array nebo MyBigArray Obvykle typy a konstanty začínají velkými písmeny, proměnné malými GetX/SetX konvence pro metody v C++ apod.

Pojmenování všech smysluplných konstant Žádné int x[ 100] ani case 27: Jaké jiné konstanty než smysluplné by měly být ve zdrojových textech?

Nepoužívat deprecated features const a = 123; bool b; b++; char *s = "abcd"; <stdlib.h>

Page 122: Programov ání v  jazyce  C

122

Dynamické seznamy

struct osoba { char jmeno[20]; int narozen; osoba *dalsi;};

osoba *zamestnanci;

hlava seznamu

jmeno Novak

narozen 1905

dalsi

Jason

1948

Drson

1990

ukazatel na další

konec seznam

u

hlava seznamu

ukazatel na další

Page 123: Programov ání v  jazyce  C

123

Vyhledání prvku

osoba *os;for( os=zamestnanci; os; os=os->dalsi) { if( os->narozen == 1972) return os;}return 0;

zamestnanci os

Karel

1972

Novak

1905

Jason

1948

Drson

1990

přechod na další prvek

pozorna konec!

lezu po krabicích

Page 124: Programov ání v  jazyce  C

124

Přídání prvku na začátek

osoba *zamestnanci;...

osoba *novy;if( ! (novy = malloc(sizeof(osoba)))) error();strcpy( novy->jmeno, "Novak"); novy->narozen = 1905;novy->dalsi = zamestnanci;zamestnanci = novy;

nový prvek

Novak

1905

Jason

1948

Drson

1990

zamestnancizařazení do seznamu

novy

Page 125: Programov ání v  jazyce  C

125

Přídání prvku doprostřed

osoba *sem, *novy;if( ! (novy = malloc(sizeof(osoba)))) error();strcpy( novy->jmeno, "Karel"); novy->narozen = 1972;novy->dalsi = sem->dalsi;sem->dalsi = novy;

Novak

1905

Jason

1948

Drson

1990

zamestnanci sem Karel

1972

novy přepojení

ukazatelů

Page 126: Programov ání v  jazyce  C

126

Dynamické datové struktury - fronta

struct prvek { int n; prvek *dalsi;};

struct fronta { prvek* prvni; prvek* posledni;};

init( fronta* f);put( fronta* f, int n);int get( fronta* f);

fronta f;init( &f);put( &f, 1);x = get( &f);

1

ukazatel na další

2 3

prvni:

posledni:

fronta

prvek prvek prvek

poslední prveknulový ukazatel

Page 127: Programov ání v  jazyce  C

127

Další dynamické struktury

obousměrně propojený lineární seznambinární strom, vyvážený stromobecný strom, obecný grafgumové poleasociativní pole

mnoho DS ve standardních knihovnách - C++ STL

Page 128: Programov ání v  jazyce  C

128

Oblíbené chyby – struktura programu

Chybějící nebo přebývající středník:for (i=0; i<n; i++);{ ... }funkce();{ ... }

Přehozené parametry funkcí nebo části konstrukce:char text[20];strcpy( "Chyba!", text);for( i=0; i++; i<20)...

Nezapomínat na break v konstrukci switch Pozor na define (raději takhle vůbec nepoužívat):#define uint int*uint p1,p2;#define N 100;int delka=N+1; /* rozvine se: int delka=100;+1; */#define square (x) x*x

K čemu patří else?if(podmínka1)  if(podmínka2) /* akce */else /* jiná akce */

Page 129: Programov ání v  jazyce  C

129

Oblíbené chyby – výrazy

Celočíselné dělení:x=1/3;

Zaokrouhlovací chyby:for (x=0; x!=1.0; x+=0.1)...

Odporující si parametry u printf:printf("%d",1.25);

Záměna & | a && ||a=1; b=2; if(a&b)...

Zkrácené vyhodnocování logických výrazů Pozor na záměnu znaků:a=1; if (a<1,5)...

Pozor na prioritu operátorů. Závorka navíc nikdy neuškodí. Nespoléhat na pořadí vyhodnocování (následující výstupy nejsou definovány):printf("%d %d",i++,i--);

a[i++]=b[i++] může být přeloženo 3 způsoby if (0<x<1)...

Page 130: Programov ání v  jazyce  C

130

Oblíbené chyby – ukazatele

Neinicializované proměnné, zvl. ukazatele:char *text;strcpy( text, "Chyba!");

Ukazatel na proměnnou, která už neexistuje:char text[20];strcpy( text, ....);return text;

Chybějící nebo naopak přebývající & u parametru předávaného ukazatelem:scanf( "%d %s", i, &text);

Page 131: Programov ání v  jazyce  C

131

Co (a proč ) dělá tento program?

#define _ F-->00||F-OO--;

int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()

{

_-_-_-_

_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_

_-_-_-_

}

Page 132: Programov ání v  jazyce  C

132

==================

Page 133: Programov ání v  jazyce  C

133

Nepoužité slajdy

Page 134: Programov ání v  jazyce  C

134

Preprocesor

/*...*/int printf( const char *, ...);/*...*/

int getch();int putch();/*...*/

#include <stdio.h>#include <conio.h>int main( int argc, char ** argv){ printf( “Hello\n”); getch(); return 0;

/*...*/int printf( const char *, ...);/*...*/int getch();int putch();/*...*/int main( int argc, char ** argv){ printf( “Hello\n”); getch(); return 0;}

stdio.h

conio.h

hello.c

Page 135: Programov ání v  jazyce  C

135

Typy souborů

Microsoft Unix

.c .c Zdrojový kód C

.cpp .C .cc .cpp Zdrojový kód C++

.h .h Hlavičkový soubor C

.h .hppnebo bez přípony

.h .H .hh .hppnebo bez přípony

Hlavičkový soubor C++

.i .i (Výstup preprocesoru)

.asm .s (Přeložený kód v assembleru)

.obj .o Objektový modul

.lib .a Knihovna

.dll .so Dynamicky linkovaná knihovna

.exe bez přípony Spustitelný program

Page 136: Programov ání v  jazyce  C

136

C a C++

C++ nadstavba C (až na drobné výjimky) lepší C (reference, implicitní parametry, přetěžování funkcí) podpora pro datovou abstrakci objektově orientované programování zajímavé a pokročilé vlastnosti – výjimky, RTTI, šablony výborné objektové knihovny - STL

encapsulation zapouzdřeníinheritance dědičnostpolymorphysm polymorfismus

Page 137: Programov ání v  jazyce  C

137

Výhody a nevýhody jazyka C

přenositelnost

standardní součást UNIXu dědictví UNIXu

úsporná syntaxe nepřehledná syntaxe

dostupnost a kvalita kompilátorů

slabá kontrola při kompilaci

využívání prostředků OS žádná kontrola za běhu

spojitelnost s jinými jazyky

použitelnost pro OS a I/O

použitelnost pro pračky

řezničiny řezničiny

Page 138: Programov ání v  jazyce  C

138

Zajímavé vlastnosti C

Přenositelnost velikost int, direktivy

Zahození hodnotyPříkazem může být výraz (např. přiřazovací výraz)

Jazyk samotný nezná žádné 'standardní funkce' include - definice funkcí, typů, dat, ... bohaté knihovny, různá prostředí - různé knihovny

(pračky nepotřebují souborový výstup)

Neexistence automatických kontrol - chybové kódy C++ - mechanismus výjimek časté 'padání' nebo neočekávané chování programu

Váňovo paradoxon

čím vyšší jazyk tím méně

přenositelný

Page 139: Programov ání v  jazyce  C

139

Přeložený kód - modul

hello.obj

...pushcall...call...ret

_main

_printf_getch

'H', 'e', 'l', 'l', 'o', 10, 0Data

Export

Import

Code

Page 140: Programov ání v  jazyce  C

140

Spojování modulů

hello.ob

j...callcall...

_main

_printf_getch

Export

Import

Code cstart.o

bj...call...

entry point

_main

Export

Import

Code printer.o

bj...

_printfExport

Import

Code

Page 141: Programov ání v  jazyce  C

141

Dynamická vs. lokální data

char buf[32] = "abc";

char* fce( int c){ char* s; s = malloc( 20); strcpy( s, "ahoj"); *s = c; return s;}

"abc""ahoj"

???

"ahoj"

Lokálnízásobník

Dynamickáheap

Globální

buf:

c:

s:

lokální ukazatelna dynamická data

Page 142: Programov ání v  jazyce  C

142

Dynamická vs. lokální data

char buf[32] = "abc";

char* fce( int c){ char* s; s = malloc( 20); strcpy( s, "ahoj"); *s = c; return s;}

{ char* str = fce( 'X');

"abc""ahoj"

'X'

"Xhoj"

Dynamickáheap

Globální

buf:

c:

s:

str zatím není

inicializované

str:

Lokálnízásobník

???

Page 143: Programov ání v  jazyce  C

143

Dynamická vs. lokální data

char buf[32] = "abc";

char* fce( int c){ char* s; s = malloc( 20); strcpy( s, "ahoj"); *s = c; return s;}

{ char* str = fce( 'X');

"abc""ahoj"

"Xhoj"

Dynamickáheap

Globální

buf:

návrat ukazatelena dynamická data

str:

Lokálnízásobník

Page 144: Programov ání v  jazyce  C

144

Ukazatele na struktury

struct osoba { char jmeno[20]; int narozen;};

osoba ja, zamestnanci[1000];

osoba *novy;

if(!(novy = malloc(sizeof(osoba)))) error();novy->narozen = 1968;strcpy( novy->jmeno, "Novak");

Pozor! *x.y *(x.y)x->y (*x).y

Page 145: Programov ání v  jazyce  C

145

Ladicí implementace alokačních funkcí

Obložit každý alokovaný blok prostorem vyplněným značkami

Při dealokaci zkontrolovat neporušenost značek a změnit je

void * my_malloc( size_t s){ char * p = (char *)malloc( s+sizeof(size_t)+2*AB_SIZE); if ( ! p ) return 0; *(size_t *)p = s; memcpy( p+sizeof(size_t), AB_FILL, AB_SIZE) memcpy( p+sizeof(size_t)+AB_SIZE+s, AB_FILL, AB_SIZE) return p+sizeof(size_t)+AB_SIZE;}

void my_free( void * vp){ char * p; if ( ! vp ) ERROR(); p = (char *)vp - (sizeof(size_t)+AB_SIZE); if ( memcmp( p+sizeof(size_t), AB_FILL, AB_SIZE) ) ERROR(); if ( memcmp( p+sizeof(size_t)+AB_SIZE+*(size_t *)p,

AB_FILL, AB_SIZE) ) ERROR(); /* ... zmenit znacky ... */ free( p); }

Page 146: Programov ání v  jazyce  C

146

Next run

podrobné spojování modulů až nakonec po direktiváchtypové konstrukce raději až po pointrechswitch, for s příklademsystematicky bloky, vnořování, deklarace a inicializace, C / C++ / jazyky s bl. str.strlen postupněslajdy na argvint typy – size_t, ptrdiff_t, wchar_t

Dvojrozměrné pole – jak ho alokovatFunkce printfFunkce random - pouzitiŘetězce a argumenty příkazové řádky rozdělit do dvou přednášek84-87, 109 – 116, 138-139 od Filipa pridat do slajducallock