Je C++ vhodné pro embedded systémy?



Podobné dokumenty
PREPROCESOR POKRAČOVÁNÍ

Teoretické minimum z PJV

Jazyk C++ 1. Blok 3 Objektové typy jazyka C++ Třída. Studijní cíl. Doba nutná k nastudování. Průvodce studiem

Jazyk C++ II. Výjimky

20. Projekt Domácí mediotéka

Programování v C++ 3, 3. cvičení

Programování v C++ 2, 4. cvičení

int => unsigned int => long => unsigned long => float => double => long double - tj. bude-li:

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

8) Jaké jsou důvody pro použití víceprůchodového překladače Dříve hlavně kvůli úspoře paměti, dnes spíše z důvodu optimalizace

Jazyk C++ I. Šablony 2

PROGRAMOVÁNÍ MIKROPOČÍTAČŮ CVIČENÍ 10

Jazyk C++ I. Polymorfismus

Ukazka knihy z internetoveho knihkupectvi

IUJCE Přednáška č. 11. další prvky globální proměnné, řízení viditelnosti proměnných, funkcí

MATURITNÍ OTÁZKY ELEKTROTECHNIKA - POČÍTAČOVÉ SYSTÉMY 2003/2004 PROGRAMOVÉ VYBAVENÍ POČÍTAČŮ

Jazyk C++ II. Dynamické identifikace typů

přetížení operátorů (o)

Architektury CISC a RISC, uplatnění v personálních počítačích

Programování II. Polymorfismus

INTELIGENTNÍ SNÍMAČE

PB161 Programování v jazyce C++ Přednáška 7

PB161 Programování v jazyce C++ Přednáška 7

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

GRAFICKÉ ROZHRANÍ V MATLABU PRO ŘÍZENÍ DIGITÁLNÍHO DETEKTORU PROSTŘEDNICTVÍM RS232 LINKY

Programování II. Třídy a objekty (objektová orientovanost) 2018/19

Aplikace Embedded systémů v Mechatronice. Michal Bastl A2/713a

PROGRAMOVÁNÍ ŘÍDÍCÍCH SYSTÉMŮ

Úvod do architektur personálních počítačů

Dědění, polymorfismus

Projekty pro výuku programování v jazyce Java

Polymorfismus. Časová náročnost lekce: 3 hodiny Datum ukončení a splnění lekce: 30.března

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

Charakteristika dalších verzí procesorů v PC

Jazyk C++ II. Šablony a implementace

V dalších letech se pak začaly objevovat první normy pro jazyk C++ (ISO/IEC 14882:1998; ISO/IEC 9899:1999; ISO/IEC 14882:2003; ISO/IEC 14882:2011).

Střední škola pedagogická, hotelnictví a služeb, Litoměříce, příspěvková organizace

Generické programování

PROGRAMOVÁNÍ V C++ URČENO PRO VZDĚLÁVÁNÍ V AKREDITOVANÝCH STUDIJNÍCH PROGRAMECH ROSTISLAV FOJTÍK

Abstraktní třídy, polymorfní struktury

ZPRACOVÁNÍ NEURČITÝCH ÚDAJŮ V DATABÁZÍCH

Paměti a jejich organizace

Operační systémy. Přednáška 8: Správa paměti II

Základy objektové orientace I. Únor 2010

Uživatelem řízená navigace v univerzitním informačním systému

Jazyk C++ I. Šablony

SPECIFICKÝCH MIKROPROGRAMOVÝCH ARCHITEKTUR

1. Programování proti rozhraní

Sběrnicová struktura PC Procesory PC funkce, vlastnosti Interní počítačové paměti PC

Tabulka symbolů. Vazba (binding) Vazba - příklad. Deklarace a definice. Miroslav Beneš Dušan Kolář

Technické prostředky počítačové techniky

Aplikace Embedded systémů v Mechatronice. Michal Bastl A2/713a

ÚAMT FEKT VUT. mikroprocesor Rabbit. Diplomová prá ce. Tomá škreuzwieser. Brno

Zvyšování kvality výuky technických oborů

Další aspekty architektur CISC a RISC Aktuálnost obsahu registru

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Práce s velkými sestavami

Kapitola 1: Co je Microsoft Access? 27 Kapitola 2: Mnoho tváří aplikace Microsoft Access 41 Kapitola 3: Návrh databázové aplikace 75

IB111 Programování a algoritmizace. Objektově orientované programování (OOP)

Systémová volání Mgr. Josef Horálek

Distanční opora předmětu: Programování v jazyce C Tématický blok č. 8: Dynamické datové struktury, ladění programů Autor: RNDr. Jan Lánský, Ph.D.

Programování II. Abstraktní třída Vícenásobná dědičnost 2018/19

10. blok Logický návrh databáze

Programování v C++ 1, 1. cvičení

Výčtový typ strana 67

Jakub Čermák Microsoft Student Partner

Mělká a hluboká kopie

<surface name="pozadi" file="obrazky/pozadi/pozadi.png"/> ****************************************************************************

Programování v jazyce C a C++

Principy objektově orientovaného programování

Procesor. Procesor FPU ALU. Řadič mikrokód

Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost rozhraním a výjimkám.

LED_007.c Strana: 1/5 C:\Michal\AVR\Výukové programy\archiv\ Poslední změna: :01:48

Telekomunikační sítě Protokolové modely

Šablonové metaprogramování v C++ Miroslav Virius KSI FJFI ČVUT

PB161 Základy OOP. Tomáš Brukner

) informace o stavu řízené veličiny (předávaná řídícímu systému) - nahrazování člověka při řízení Příklad řízení CNC obráběcího stroje

Úvod do programovacích jazyků (Java)

Dynamicky vázané metody. Pozdní vazba, virtuální metody

INFORMAČNÍ A KOMUNIKAČNÍ TECHNOLOGIE. Ing. Jaroslav Adamus. Gymnázium, SOŠ a VOŠ Ledeč nad Sázavou

11. Přehled prog. jazyků

Virtuální metody - polymorfizmus

Kolaborativní aplikace

Aritmetika s velkými čísly na čipové kartě

Více o konstruktorech a destruktorech

Algoritmizace a programování

PB161 programování v C++ Výjimky Bezpečné programování

Programování v C++ VI

PB161 Programování v jazyce C++ Přednáška 10

Zpracování deklarací a přidělování paměti

Principy operačních systémů. Lekce 6: Synchronizace procesů

SYSTÉM PRO AUTOMATICKÉ OVĚŘOVÁNÍ ZNALOSTÍ

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

Architektura počítače

Opakování programování

Konfigurace řídicího systému technikou Hardware In The Loop

Příkazy preprocesoru - Před překladem kódu překladačem mu předpřipraví kód preprocesor - Preprocesor vypouští nadbytečné (prázdné) mezery a řádky -

PROCESOR. Typy procesorů

N e j č a s t ě j š í d o t a z y k e k u k i t V

UŽIVATELSKÁ DOKUMENTACE PRO DODAVATELE. Stav ke dni v. 2.0

Transkript:

Je C++ vhodné pro embedded systémy? Ing. Miloš Čábel, +420 511 115 051, cabel@centrum.cz Ústav Automatizace a Měřicí Techniky Fakulta Elektrotechniky a Komunikačních Technologií Vysoké Učení Technické v Brně Úvod Celá řada embedded aplikací se v dnešní době programuje v jazyce C. Ale i zde platí, že složitost programů exponenciálně roste. Proto se objevuje celá řada trendů jak tuto rostoucí složitost zvládat. Jednou z možných řešení je přesunout vývoj z C na C++. Panuje ale obecně celá řada pochybností o náročnosti programů napsaných v C++ vůči aplikacím napsaným v jazyce C. Lze najít celou řadu článků porovnávajících C s C++, ale ty většinou nezohledňují specifika embedded aplikací. A pokud ano, tak si výsledky často odporují. Lze najít například článek, dokazující že přepsáním algoritmu z C++ urychlili autoři celý výpočet několikanásobně. A naopak je možno si přečíst si i řadu článků, jak je program napsaný v C++ rychlejší než v C. Co si z toho tedy vybrat? Na to se v tomto článku zaměříme. 1. Embedded systém Pokud si nejste jisti, co znamená termín "embedded systém", pak lze jako názorný příklad uvést mobilní telefon, mikrovlnná trouba, televize s teletextem, tiskárna, pokojový termostat, DVD nebo MP3 přehrávač, automatická pračka, systém řízení ABS, GPS navigace, router a mnoho dalších většinou inteligentních zařízení. Existuje několik různých, více či méně výstižných definicí. Jedna z těch výstižnějších popisuje embedded systém jako výpočetní systém s velkou vazbou mezi software a hardware, který je specializován k vykonávání nějaké konkrétní funkce. Slovo embedded (česky "vložený") vystihuje fakt, že takovéto systémy jsou obvykle součástí nějakého většího systému. Vícero vložených systémů může spolupůsobit v jednom nadřazeném systému. 1.1. Odlišnosti embedded systémů od běžných počítačů Největší rozdíly vyplývají z definice. Je to vazba na konkrétní hardware a předem daná množina funkcí daného systému. Při vývoji těchto systémů se obvykle hodnotí parametry jako je spotřeba (doba provozu při napájení bateriemi), cena, objem, váha, spolehlivost, robustnost, přesnost a podobně. Potřebný mikroprocesor (či mikrokontrolér, v tomto článku je nemusíme rozlišovat) se obvykle vybírá ten nejjednodušší, který dokáže splnit požadavky systému. Stejně tomu je i s pamětí, pokud není integrována na jednom čipu spolu s mikrokontrolérem. Z toho poměrně jasně plyne, že efektivita programu má přímý vliv na cenu a parametry systému. Efektivitou se rozumí jak velikost kódu, tak jeho rychlost. Velikost kódu a nároky na datovou paměť mají vliv na cenu a spotřebu systému. Pokud reakce programu na vnější událost vyžaduje například kolem 100 strojových cyklů, můžeme několikanásobně zpomalit taktovací kmitočet oproti programu, který na stejnou událost potřebuje až několik tisíc strojových cyklů. Nižší kmitočet znamená nižší spotřebu a ta může znamenat delší výdrž baterií nebo jednodušší napájecí obvod. 21-1

2. Norma jazyka C a C++ Jazyk C++ vychází z jazyka C a proto podporuje všechny konstrukce jazyka C. Přesto lze narazit na několik odlišností. Pro jazyk C byla vydána norma ANSI již v roce 1989, novější ISO/IEC potom v roce 1990 a v roce 1999 V případě potřeby budeme tyto normy v článku označovat jako C90 a C99. Norma ANSI/ISO pro jazyk C++ byla vydána v roce 1998. Je zde zřejmé, že vývoj obou jazyků probíhá paralelně, a drobné odchylky se tudíž mohou vyskytnout i v budoucnu. Norma C99 obsahuje skutečně několik detailů, které nejsou ani v C90 a ani v C++. Větším problémem, než drobné odchylky v normách, je častěji podpora normy v kompilátorech, i když u dobrých kompilátorů je podpora normy na vysoké úrovni a s novějšími verzemi se stále zlepšuje. 2.1. Nové prvky jazyka C++ Největším rozdílem C++ oproti C je podpora objektově orientovaného programování. Základními stavebními kameny objektově orientovaného programování jsou abstrakce, dědičnost a polymorfismus. Jazyk C++ umožňuje vytvářet třídy, které tvoří abstraktní datové typy. Třídy zapouzdřují implementaci od vnějšího rozhraní. Dále mohou využívat jednoduchou a vícenásobnou dědičnost (tzn., že třída může být potomkem několika různých tříd). Polymorfismus je realizován především virtuálními funkcemi. Mezi další vlastnosti patří přetížené funkce a operátory, jmenné prostory, šablony, virtuální dědičnost, mechanismus výjimek, konstantní proměnné, spřátelené funkce či třídy a v neposlední řadě standardní šablonová knihovna obsahující řadu běžně používaných algoritmů. 3. Náročnost nových vlastností jazyka C++ Celá řada nových vlastností nemá výraznou režii při vykonávání programu. Jsou to případy, kdy kompilátor dokáže v čase překladu rozhodnout, která konkrétní funkce se zavolá (časná vazba). Týká se to dědičnosti, kdy lze v době překladu rozlišit, zda se bude volat metoda předka nebo potomka. Stejná situace se týká i přetížených funkcí (více funkcí má stejné jméno, ale liší se parametry - kompilátor rozezná, která funkce se má zavolat) a operátorů. 3.1. Přetížené operátory Přetížené operátory výrazně zjednodušují a zjednodušují zápis programu. Jedinou drobnou nevýhodou z hlediska programátora embedded aplikace může být, že jednoduchý vzorec může trvat i poměrně dlouhou dobu. To ale není novinka C++, i v C jsou operátory přetížené a například sčítání dvou krátkých celočíselných typů znamená ve výsledném kódu několik instrukcí, zatímco sečtení dvou čísel v plovoucí řádové čárce volá knihovní funkci, která může součet zpracovávat i několik milisekund. 3.2. Jmenné prostory Také jmenné prostory (namespace) neznamenají zátěž za běhu programu, pouze znamenají rozšíření identifikátorů a tudíž umí řešit kolizi názvů v rozsáhlejších projektech. Jmenné prostory umožňují zjednodušit názvy v jednotlivých prostorech. Takže odpadá v C poměrně časté přidávání zkratek nebo jmen modulů do jmen funkcí exportovaných z modulu. 21-2

3.3. Dědičnost Dědičnost nemá nároky při běhu programu, až na výjimku konstruktorů a destruktorů, které musí volat postupně konstruktory (případně destruktory) všech svých předchůdců. Naopak můžeme při vhodném návrhu ušetřit část kódu, který obsluhuje společné části příbuzných tříd a nemusí se tedy několikrát opakovat. 3.4. Virtuální metody Mezi náročné vlastnosti patří virtuální metody (funkce), kdy každý objekt má pointer na tabulku ukazatelů na virtuální metody a přístup k těmto metodám je díky několikanásobnému pointerovému přístupu pomalejší. Velmi podobná situace nastává v případě virtuální dědičnosti, kde potomek má referenci na předka a pro volání metod předka musí použít složitější přístup přes referenci. Náročnost tedy spočívá v potřebné paměti pro tabulku virtuálních metod a pointerů na tuto tabulku. Dále přístup k metodám přes tyto tabulky je pomalejší. Třetím aspektem je, že tyto metody nemohou být vloženy do místa volání (inline). 3.5. Výjimky Systém výjimek je velmi elegantní a dokáže dobře zpřehlednit zdrojový kód, kde odděluje detekci chyby, zpracování výsledků funkce a reakci na chybu. Bohužel je tento mechanismus poměrně náročný. Poměrně často ani není podporován kompilátory pro embedded aplikace. V případě real-time systémů, kde obvykle musí systém reagovat v pevně daném čase, má tento systém další výraznou nevýhodu, a tou je neznámá doba reakce na detekovanou chybu. 3.6. Šablony Šablony jsou zvláštní kapitolou. Ze svého principu se šablony instancují v době překladu (instancí šablony je třída nebo funkce). Takže za běhu programu neznamenají časovou zátěž, tak jako virtuální funkce. Pokud ale použijete tento mocný nástroj neopatrně, může vám velmi snadno narůst velikost kódu nad možnosti daného embedded systému. S tím spojená druhá nevýhoda je, že se hůře odhaduje velikost výsledného kódu při použití šablon. Na druhou stranu můžete s pomocí šablon vytvořit nejrůznější pomůcky pro kontrolu správnosti kódu při překladu, šablonovou knihovnu funkcí založených na zásadách a podobně. Knihovna založená na zásadách implementuje nějaký algoritmus a zásady specifikují některé postupy, které knihovna použije. Zásady mohou například určovat, jakým způsobem se alokuje paměť nebo zda a jak má algoritmus knihovny pracovat s mutexy. Výhodou je, že zásady si vybírá uživatel knihovny, nikoli její autor. Toto téma je ale poněkud pokročilé a případný zájemce si je může nastudovat v literatuře, například [03]. 4. Slabiny jazyka C v porovnání s C++ 4.1. Makra a konstanty Makra v C jsou užitečným a často užívaným nástrojem. Bohužel mají v sobě několik problémů, která činí makra snadno zranitelnými. Sice lze celou řadu těchto problémů potlačit, ale nikoli zcela odstranit. Při použití maker místo symbolických konstant je problémem, že tyto konstanty nemají typ. To zabraňuje kompilátoru kontrolovat použití 21-3

těchto konstant správně. Asi nejlepší řešení při použití maker vypadá takto: #define KONSTANTA ((uint8)42) #define VELKA_KONSTANTA ((uint32) 100000L) C++ kompilátory mají konstantní proměnné, které tyto problémy nemají. const uint8 KONSTANTA = 42; V C jsou konstantní proměnné implementovány jako jakékoliv jiné proměnné. Jediným rozdílem je, že je kompilátor nedovolí jednoduše změnit. Tento přístup je v drtivé většině pomalejší a s delším kódem, než použití makra. Makro se totiž nahradí výslednou hodnotou již preprocesorem a kompilátor pracuje již jen výslednou hodnotou. V C nejsou konstantní proměnné dostatečně konstantní, v době překladu je kompilátor nepovažuje za konstanty a tak je nelze použít jako konstantní výraz při kompilaci. Následující příklad nelze zkompilovat v C, protože velikost pole musí být známa v době překladu ale v C++ je možno zkompilovat tento příklad zcela bez problémů. int const velikost_pole = 10; int pole[velikost_pole]; V C lze poměrně jednoduše získat adresu konstantní proměnné a tuto proměnnou změnit pomocí přístupu přes pointer. Potom se tato konstantní proměnná skutečně změní a to v celém programu. Naštěstí leží často taková proměnná v nepřepisovatelné paměti. V C++ jsou konstantní proměnné, stejně jako makra, přeloženy obvykle jako konstanty v instrukcích při plnění registrů. Pokud leží taková instrukce v nepřepisovatelné paměti (např. FLASH), tak nemůže být změněna jen tak nějakou chybkou v software. 4.2. Makra a funkce U některých jednoduchých a rychlých funkcí je režie spojená s voláním funkce a návratem větší nebo srovnatelná s provedením samotného těla funkce. Prostě by bylo jednodušší nahradit volání funkce jejím tělem. V C se to dělá pomocí maker s parametry (anglicky "function like macro"). To má ale své problémy, které se musí řešit důsledným závorkováním všech parametrů a celého výrazu. I tak se ale mohou objevit problémy, pokud se některý z parametrů použije v makru vícekrát. Z toho důvodu definuje C++ a nejnovější norma C99 klíčové slovo inline, které znamená, že tělo funkce se vloží přímo do místa volání. Např. #define max(a,b) (((a)>(b))?(a):(b)) se při použití maximum = max(leva++, prava++); rozbalí na výraz: maximum = (((leva++)>(prava++))?(leva++):(prava++)); což rozhodně nebude tak, jak si programátor představoval. V případě inline funkce inline int max(int a, int b) { return ((a>b)?a:b); } se výraz maximum = max(leva++, prava++); provede podle očekávání. Dalším problémem maker je, že v případě syntaktické chyby hlásí kompilátor chybu v místě použité (volání) makra. Najít chybu v makru, které používá několik dalších 21-4

maker a ty jsou opět postaveny na použití dalších maker, je velmi nepříjemná záležitost. Pokud makro není vůbec v programu použito, tak se neprovádí žádná kontrola makra. To může být výhodou, ale častěji se jedná o nevýhodu, kdy při psaní makra není kontrola kompilátoru k dispozici. Pokud naopak používáme v kódu makro, které je prozatím prázdné, ale jeho použití má syntaktickou vadu, tak se nám tato vada projeví až v okamžiku, kdy dané makro doplníme. 4.3. Zapouzdření V C lze řešit pomocí rozdělení jednotlivých modulů do souborů. Proměnné a funkce, které nemají být viditelné mimo modul, lze označit jako static. Pokud potřebujeme v nějakém modulu zpřístupnit funkci nebo proměnnou pro jeden jiný modul, pak ji musíme zpřístupnit pro všechny. Je sice možné nezveřejňovat deklaraci funkce či proměnné a kopii deklarace umístit též do spřáteleného modulu. Ovšem toto řešení není moc vhodné, protože musíme udržovat obě deklarace (v modulu samotném a ve spřáteleném modulu) konzistentní, což může být v případě údržby programu problém. C++ umožňuje privátní metody a atributy. Kromě toho umožňuje mechanismus spřátelených funkcí nebo tříd, které mají přístup i k privátním proměnným dané třídy. Výhodou přátel je, že deklarace třídy je stále jen jedna a přímo v deklaraci třídy vidíme kdo další má přístup k privátním metodám a atributům. Při využití mechanismu dědičnosti je možno použít chráněných atributů a metod, ke kterým mají přístup potomci. 4.4. Problémy s přechodem na C++ Až na pár výjimek by měl být program napsaný v C přeložitelný i C++ kompilátorem. Obecně platí, že C++ kompilátor má mnohem přísnější typovou kontrolu a některé konstrukce, které jsou v C korektní, budou problémem v C++. V tabulce najdete stručný seznam toho, co by vám C kompilátor měl umožnit, ale C++ vám odmítne přeložit. Nutno poznamenat, že následující seznam rozhodně nepatří do dobrého programátorského stylu. Ani u novějších C kompilátorů se následující věci neobejdou alespoň bez varování. 21-5

C++ Funkce nemá implicitní návratový typ pokud funkce vrací nějakou hodnotu, musí příkaz return vždy hodnotu vracet. Striktní kontrola prototypů funkce. void foo(); nemá žádné parametry C Implicitní návratový typ funkce je int lze použít return bez parametrů i ve funkci s návratovou hodnotou. Lze použít prototyp funkce bez udání parametrů. void foo(); může mít parametry. Pro funkce v C knihovně volané z C++ kódu je potřeba přidat klíčové slovo extern "C". Naštěstí to lze poměrně elegantně vyřešit v hlavičkových souborech pro všechny funkce jednou ranou. Výhodou této konstrukce je, že bez problémů funguje jak v C, tak v C++. Proto může být bez obav používána ve všech hlavičkových souborech, a to i v projektech, které nikdy nebudou kompilovány C++ kompilátorem. #ifdef cpluplus extern "C" { #endif... void PrototypCFunkce(void);... #ifdef cpluplus } #endif 5. Jazyk EC++ Tato zkratka znamená Embedded C++. U zrodu tohoto dialektu C++ stáli hlavní japonští výrobci mikroprocesorů NEC, Hitachi, Fujitsu a Toshiba. Účelem tohoto počinu bylo vybrat takovou podmnožinu jazyka C++, která přinese hlavní výhody jazyka C++ ale neobsahuje mechanismy nevhodné a potenciálně nebezpečné pro embedded systémy. 5.1. Seznam konstrukcí C++ které byly vynechány v EC++ 1. Vícenásobná dědičnost a virtuální dědičnost 2. Nové způsoby přetypování 3. Specifikátor mutable 4. Jmenné prostory 5. Identifikace typu za běhu programu (runtime type information) 6. Výjimky 7. Šablony Vícenásobná dědičnost bohužel přináší řadu problémů a to pro nejen programátora ale i pro kompilátor. Z toho důvodu celá řada objektově orientovaných jazyků nepodporuje vícenásobnou dědičnost. Jeden z příkladů je dědičnost typu diamant, kde třídy B a C jsou potomci nějaké třídy A. Potom má třída D, potomek třídy B a C, atributy z prapředka A dvakrát. To lze sice řešit pomocí virtuální dědičnosti, ale výsledek není většinou tak 21-6

efektivní. Násobná dědičnost je poměrně náročná na pochopení i údržbu. Mutable znamená, že objekt deklarovaný jako const se může změnit. V embedded systémech se ale konstantní objekt ukládá do paměti typu ROM. Potom takový modifikátor přináší jen zmatek a komplikace. 6. Efektivní používání jazyka C++ V článku [09] autor uvádí, že přepsáním C++ kódu z tříd na struktury a globální funkce se doba výpočtu zrychlila dvojnásobně. A současně se výrazně zmenšila velikost programu a použití zásobníku se také zmenšilo. Ale současně s přechodem z C++ do C byla objevena celá řada proměnných a metod, které sloužily pro výzkum v době vývoje algoritmu a pro ladění (debug) algoritmu. Dále se struktura tříd při změně na struktury zjednodušila, protože některé třídy byly pro finální algoritmus zbytečné. Pro podporu vektorů byl použit jiný algoritmus. V tomto případě lze předpokládat, že hlavní vliv mělo vyčistění programu od nepotřebných pozůstatků z doby vývoje algoritmu, nikoli přechod z C++ k C. 6.1. Základní tipy na zvýšení efektivity Členské metody mají implicitní pointer this. Pokud jej ale metoda nepotřebuje, tak ji označte klíčovým slovem static. Ušetří se tím předávání jednoho parametru. Statické atributy třídy jsou společné pro všechny instance dané třídy (objekty). Statické proměnné v modulu je lepší nepoužívat, norma to zavrhuje. Tzn. podporuje, ale v příštích verzích normy to již nemusí platit. Nešetřete klíčovým slovem const. V C++ má const mnohem více použití než v C. Její důsledné použití umožňuje lepší kontrolu a optimalizaci kompilátoru při překladu. Například: const &navratobjekt Funkce ( const int * const parametr) const Funkce vrací referenci na konstantní objekt. Parametrem je konstantní pointer na konstantní int. A konečně, funkce nemění objekt třídy. Jednoduché metody je vhodné označit jako inline, aby se vynechala režie spojená s voláním funkce. To se výrazně projeví v programech, kde je mnoho vrstev a inline expanze vede ve výsledku k velmi rychlému a efektivnímu kódu. Nepoužívejte virtuální metody zbytečně. Někdy je ale jejich použití vhodné. 6.2. Šablony Sice nejsou součástí EC++, ale umožňují velmi efektivní programové konstrukce, které se vykonávají v době překladu, a tudíž umožňují ve výsledku velmi pružně konfigurovatelný a přesto poměrně efektivní kód. Některé EC++ kompilátory podporují šablony jako rozšíření. 21-7

6.3. Další efektivní metody Zde je stručný seznam dalších technik, jak zvýšit efektivitu programu. I když se jedná o metody, které nemají souvislost s programovacím jazykem, je třeba na ně nezapomínat. Nastavení kompilátoru: Vypněte podporu pro systém výjimek, pokud je nepoužíváte. Vypněte podporu pro typové informace za běhu programu (Runtime Type Information = RTTI) Zapněte optimalizace. Dobře napsaný kód nemá většinou s velkými optimalizacemi problémy. Pokud nějaká funkce nebo modul nefunguje s velkou úrovní optimalizace, tak snižte úroveň optimalizace jen pro danou funkci či modul, nikoli pro celý projekt. Optimalizujte paměťové přístupy: Často používané proměnné dejte do nejrychlejší paměti. Některé procesory mají zrychlený přístup k jednotlivým bitům v některých oblastech paměti. Pro přenos většího bloku dat použijte DMA, pokud je k dispozici. Pro 16 a 32 bitové procesory může špatně zarovnaná proměnná degradovat rychlost přístupu. Při zpracování velkého bloku dat, který se nevejde do rychlé paměti (například obrázku) je často lepší si kousek (např. několik řádků) přenést do rychlé paměti, zpracovat a potom si zkopírovat další kousek. Je škoda přenášet na 16 a 32 bitových procesorech bloky dat bajt po bajtu. Pokud několikrát potřebujeme ve funkci nějakou proměnnou, ke které je zdlouhavý přístup (např. (ppole[i])->nejakapolozka[j]), tak bývá kratší a rychlejší si tuto hodnotu na začátku načíst do lokální proměnné a používat tuto proměnnou. Optimalizace výpočtů Na procesorech bez HW podpory plovoucí řádové čárky je aritmetika s pevnou řádovou čárkou mnohem rychlejší. Některé složité vzorce lze zjednodušit. Pro funkce lze najít v určitém rozsahu náhradu (Taylorův rozvoj, linearizace po částech, ) Někdy existuje prostě rychlejší algoritmus. A mnoho dalších metod. 7. Objektově orientované programování v C Základní mechanismy objektového programování, jako je abstrakce, dědičnost a polymorfismus, lze sice vytvořit a používat sice i v jazyce C, ale přeci jen to vyžaduje více úsilí. Fakt, že nejstarší kompilátory pro C++ kód převáděly na C, tuto skutečnost jen potvrzuje. Třídy lze nahradit strukturami, členské funkce dostanou navíc parametr na tuto strukturu jako náhradu za implicitní this. Obecně je vhodnější používat zavedené označení "me" místo this. Je to proto, aby bylo možno tento kód znovu použít i v C++ projektu. Dědičnost se může vypadat například takto: struct Predek {... } 21-8

struct Potomek { struct Predek super;... } Potomek potom může k atributu předka přistupovat pomocí me->super.nejakyatribut; a nebo ((Predek *) me)->nejakyatribut; Některé C kompilátory sice umožní použít strukturu předka jako nepojmenovanou položku ve struktuře potomka s jednodušším přístupem k položkám předka, ale toto řešení může způsobit dost komplikací při přechodu na jiný kompilátor. 7.1. Polymorfismus Virtuální metody je možno v C vytvořit, podobně jako to dělá C++ kompilátor, pomocí tabulky pointerů na virtuální metody, kdy každý objekt bude obsahovat pointer na tabulku své třídy. 7.2. Zapouzdření Přístupová práva lze rozlišovat například specifickým jménem, například privátní proměnné dvěma podtržítky na konci, chráněné jedním a veřejné bez podtržítka. Kompilátor sice nikomu nezabrání porušit přístupová práva, protože v C žádná nejsou, ale tento prohřešek lze snadno odhalit při kontrole kódu (code review). 7.3. Porovnání Problémem je, že jazyk C za programátora neudělá spoustu věcí, o které se v C++ postará kompilátor. Jedná se například o zavolání destruktoru při skončení platnosti proměnné. Případné zájemce o objektové programování v C odkážeme na literaturu [04], příloha věnovaná C+. 8. MISRA Tato zkratka znamená Motor Industry Standard Association - asociace která připravila pravidla pro bezpečné psaní programů v C pro automobilový průmysl. Tyto pravidla se ale postupně šíří i do organizací, které se nezabývají aplikacemi pro automobilový průmysl. V tomto směru je pro C++ nevýhodou, že MISRA pravidla pro C++ dosud neexistují, když se podle dostupných informací tato pravidla připravují. Pro programátory, kteří se zajímají o bezpečné psaní programů (tzn. tak aby programy pokud možno fungovaly, i když se v nějaké nepříliš související části kódu něco změní), mohou být tato pravidla užitečná. 21-9

9. Závěr V dnešní době stále rostoucích požadavků na složitost embedded systémů je přechod k C++ poměrně snadný. Největší výhodou je, že vás ani po přechodu k C++ nikdo nenutí do objektů a proto můžete i nadále používat programové moduly, které jsou napsány v C. Největším problémem může být investice do nového kompilátoru, pokud váš stávající kompilátor nepodporuje C++. Většina dnešních kompilátorů podporuje C i C++. Pasti v C++ lze omezit vhodným návrhem programu a využitím výhod C++ lze získat kód minimálně stejně efektivní jako při použití C. A navíc může být daný kód čitelnější, snadněji udržovatelný a snáze znovupoužitelný. Rozhodně dobrým startem je použití EC++ kompilátoru, který může být na konkrétní platformu dostupnější než kompletní C++ kompilátor. 10. Seznam literatury [01] Stephen Prata. 2004. Mistrovství v C++, 2. vydání. Computer press. [02] Quing Li, Caroline Yao. 2003. Real-Time concepts for embedded systems. CMP Books [03] Andrei Alexandrescu. 2004. Moderní programování v C++. Computer press. [04] Miro Samek. 2002. Practical statecharts in C/C++; CMP Books 2002 [05] EC++ Technical Committee. http://www.caravan.net/ec2plus [06] Mario Friedrich. 2007. Highly efficient C++ code and automotive - a mutual exclusion?, Embedded world [07] Dan Saks. 2007. Bail, return, jump, or... throw?; http://www.embedded.com/showarticle.jhtml?articleid=197008821 [08] Miroslav Virius. 2006. Jazyky C a C++. Grada Publishing. [09] Ketul Patel. Porting PC Based algorithms to DSPs. Embedded Edge, Fall 2003 [10] Jakob Ostergaard. 2004. C versus C++. http://unthougth.net/c++/c_vs_c++.html [11] IAR compiler user guide. http://www.iar.com/guides 21-10