NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze – Lekce 4 - Makra v jazyce C

Zpět

Upozorňujeme, že diskuze pod našimi online kurzy jsou nemoderované a primárně slouží k získávání zpětné vazby pro budoucí vylepšení kurzů. Pro studenty našich rekvalifikačních kurzů nabízíme možnost přímého kontaktu s lektory a studijním referentem pro osobní konzultace a podporu v rámci jejich studia. Toto je exkluzivní služba, která zajišťuje kvalitní a cílenou pomoc v případě jakýchkoli dotazů nebo projektů.

Komentáře
Avatar
Luboš Běhounek Satik:28.7.2014 18:14

Bacha na SQR / SQRT :)

Jinak osobně se snažím makrům vyhýbat a používám je spíše opravdu pro rozlišení debug/release, x86/x64 a nebo třeba platformy (OS), pro kterou se kompiluje.

U kratších funkcí se dá místo makra použít inline funkce a žádná režie volání funkce pak není.

Nadužívání maker dokáže kód strašně znepřehlednit, když používate makro v makru v makru v makru, tak se v tom člověk lehce zamotá.

Editováno 28.7.2014 18:15
Odpovědět
28.7.2014 18:14
https://www.facebook.com/peasantsandcastles/
Avatar
SPoon
Tvůrce
Avatar
Odpovídá na Luboš Běhounek Satik
SPoon:28.7.2014 18:55

Ahoj, díky za připomínky.

Klíčové slovo inline (C99) nebo const (C89) je převzato z jazyka C++. I když by měla být podpora těchto klíčových slov samozřejmostí, nemusí tomu tak ve všech C kompilátorech být.

Je ale pravda, že dnes se už doporučuje funkčním makrům vyhnout a místo makra pro definování hodnot je lepší použít klíčové slovo const. Přidám do článku ještě jednu podkapitolu. :)

Editováno 28.7.2014 18:55
 
Odpovědět
28.7.2014 18:55
Avatar
Odpovídá na SPoon
Libor Šimo (libcosenior):29.7.2014 7:08

Veľmi dobrý článok.
Námet témy na ďalší článok navrhujem :
pointery a pointerová aritmetika;
štruktúry, uniony a výčtové typy;
bitové operácie.
A myslím, že by bolo dobré ku každému článku vymyslieť cvičenia, aby sme si to mohli vyskúšať prakticky.

Odpovědět
29.7.2014 7:08
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Pavel Kratochvíl :30.7.2014 6:05

Moc pěkný článek. Pěkné shrnutí problematiky. Osobně se snažím makrům spíš vyhnout.Přimlouval bych za pokračování C čka.;)

Odpovědět
30.7.2014 6:05
Ctrl+C, Ctrl+V života, ale s vlastními úpravami ...
Avatar
Bertram
Člen
Avatar
Bertram:10.8.2014 6:58

citace z článku:
Klíčové slovo const se může vyskytovat před definicí libovolné proměnné a znemožní jakkoli manipulovat s jejím obsahem. V případě, že se pokusíte hodnotu změnit, skončí proces kompilace chybou.

Takto definovaná konstanta je uložena na rozdíl od "symbolické" v paměti, takže jde její hodnota změnit pomocí ukazatele.

const int SIZE = 10;
int* p_SIZE = &SIZE;
*p_SIZE = 100;
printf("SIZE = %d\n", SIZE);
 
Odpovědět
10.8.2014 6:58
Avatar
SPoon
Tvůrce
Avatar
Odpovídá na Bertram
SPoon:10.8.2014 18:28

Ahoj,

díky za připomínku. Správně by to ale mělo být:

const int SIZE = 10;
int* p_SIZE = (int *)&SIZE;
*p_SIZE = 100;
printf("SIZE = %d\n", SIZE);

Pokud se reference nepřetypuje, měl by kompilátor zahlásit chybu.

 
Odpovědět
10.8.2014 18:28
Avatar
coells
Tvůrce
Avatar
Odpovídá na Bertram
coells:10.8.2014 20:10

Tohle je velice nebezpečný kód a není pravda, že konstanta musí být v paměti. Je několik variant, co se stane:

  1. program vypíše hodnotu 100
  2. program vypíše hodnotu 10
  3. program skončí na SEGFAULT

Konstantní hodnoty vůbec nemusí být alokované v paměti nebo dokonce v zapisovatelné paměti. Všechno záleží jenom na kompilátoru, typu zapnuté optimalizace a způsobu nalinkování knihovny.

 
Odpovědět
10.8.2014 20:10
Avatar
SPoon
Tvůrce
Avatar
Odpovídá na coells
SPoon:10.8.2014 22:05

Prováděli jsme testy na jednom typu kompilátoru a pokud byla konstantní proměnná menší jak 16-bitů, tak se chovala stejně jako konstanta zadefinovaná pomocí makra #define. To znamená, že nebyla uložena v paměti a kdekoli byla konstanta použita, byla přímo nahrazena číselnou hodnotou. Pokud byla konstanta větší, kompilátor pro ni vyhradil místo v paměti.

V tomto případě, ale souhlasím s coellsem, protože výše uvedený příklad zcela narušuje principy bezpečného programování.

 
Odpovědět
10.8.2014 22:05
Avatar
coells
Tvůrce
Avatar
Odpovídá na SPoon
coells:10.8.2014 22:28

Používám LLVM 5.1 a povedlo se mi snadno nasimulovat všechny tři situace, které jsem zmínil. Hodně vtipná je varianta 1+2, kdy mi kód vypíše současně 100 i 10.

To, co uvádíš, je dost podivné chování a moc mi nedává smysl. Spíš bych řekl, že tam byly jiné faktory, které jste přehlídli.

 
Odpovědět
10.8.2014 22:28
Avatar
SPoon
Tvůrce
Avatar
Odpovídá na coells
SPoon:11.8.2014 9:21

V případě, že je k dispozici malé množství paměti RAM (například 128 KB), což je typické pro embedded systémy, tak je velmi důležité, aby konstanty zbytečně nezabíraly potřebné místo. V takovém případě provede kompilátor optimalizaci - konstanta se do paměti neumístí a každý její výskyt přímo nahradí danou hodnotou.

Daná hodnota musí ale splnit dvě základní pravidla. Prvním je, že se na danou konstantu nikdy neodkážeme pomocí pointeru. Druhým pravidlem je, že číselná hodnota musí být velká tak, aby se vešla do jedné instrukce (to pro 16-bitovou instrukční sadu a 32-bitovou architekturu znamená, že číslo musí být velké maximálně 16-bitů).

Samozřejmě výše uvedené vlastnosti jsou "compiler specific", tedy závislé na typu použitého kompilátoru.

PS: Podle mého názoru se musí kompilátor pokaždé chovat deterministicky. Pokud tedy zareaguje ve stejné situaci pokaždé jinak (jako např. v tvém případě), není to správné chování.

Editováno 11.8.2014 9:22
 
Odpovědět
11.8.2014 9:21
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 20.