===== 3. Řídicí struktury, výrazy a funkce =====
* prezentace: {{courses:b0b36prp:lectures:b0b36prp-lec03-slides.pdf|}}
* zkrácená verze: {{courses:b0b36prp:lectures:b0b36prp-lec03-handout.pdf|}}
* zkrácená verze 2x2: {{courses:b0b36prp:lectures:b0b36prp-lec03-handout-2x2.pdf|}}
* zkrácená verze 3x3: {{courses:b0b36prp:lectures:b0b36prp-lec03-handout-3x3.pdf|}}
* přiložené demonstrační programy: {{courses:b0b36prp:lectures:b0b36prp-lec03-codes.zip|}}
--- //[[faiglj@fel.cvut.cz|Jan Faigl]] 2025/10/15 12:58//
#define BITS 4 //number of bits to print (4 to make it readable)
void print_binary(char *prefix, uint8_t n)
{
printf(prefix, n);
int mask = 1<<(BITS-1); // we need to shift 1 to BITS position, thus -1
for (int i = 0; i < BITS; ++i) {
putc((n & mask) ? '1' : '0', stdout);
mask = mask >> 1; //
}
printf("\n");
}
uint8_t a = 4;
print_binary("a dec: %d bin: ", a);
**Dotazy z přednášek**
Q: //Proč program i po stísku Ctrl+D dále pokračuje v načítání vstupu?//
Je to proto, že Ctrl+D bylo stisknuto pro nějaký rozepsaný vstup, který nebyl programu ještě odeslán klávesou ''Enter'', resp. znakem nového řádku.
Vstup programu na ''stdin'' je v našem případě předáván prostřednictvím emulátoru terminálů, který je ve výchozím nastavení řádkově orientovaný, tj. náš vstup je programu předám po stisku klávesy ''Enter''. Stiskem kombince ''Ctrl+D'' vyvoláme předání aktuálního vstupu programu. Pokud je aktuální vstup prázdný, generuje terminál ''EOF'' (End Of File), standardní vstup je uzavřen a následně čtení např. funkcí ''scanf()'' nebo ''getchar()'' vrací hodnotu EOF (-1). Více informací lze nalézt např. v manuálové stránce [[https://www.freebsd.org/cgi/man.cgi?query=termios&sektion=4|termios]] v části //Special Characters// znak ''EOF''.
|''EOF'' | //Special character on input and is recognized if the ICANON flag is set. When received, all the bytes waiting to be read are immediately passed to the process, without waiting for a newline, and the EOF is discarded. Thus, if there are no bytes waiting (that is, the EOF occurred at the beginning of a line), a byte count of zero is returned from the read(), representing an end-of-file indication. If ICANON is set, the EOF character is discarded when processed.// |
Q: //Jak mohu porovnat dva soubory?//
Kromě použítí příkazu ''diff'' existují další nástroje, např. [[https://meldmerge.org/]], případně konzolový ''vimdiff'' nebo grafický ''gvimdiff'' editoru [[https://www.vim.org/|vim]], více např. [[https://www.zdrojak.cz/clanky/vimdiff-nastroj-drsnaku/|vimdiff-nastroj-drsnaku]].
Q: //Proč kompilátor hlásí chybu chybějícího znaku nového řádku na konci souboru?//
Při kompilaci programu bez znaku konce řádku na konci souboru, např. při kompilaci ''clang -pedantic -Wall -Werror main.c'', dojde k chybě.
error: no newline at end of file [-Werror,-Wnewline-eof]
Je do dáno [[https://gcc.gnu.org/legacy-ml/gcc/2003-11/msg01568.html|historickým rozhodnutím]], že neprázdný zdrojový soubor by měl být zakončem znakem nového řádku. Je tak součástí standardu jazyka.
Dobrý důvod proč je vhodné zakončovat soubory koncem řádku je například při použit vložení souborů příkazem preprocesoru ''#include'', který nevkládá nový řádek, přestože to mnoho moderních kompilátorů dělá. Stále však platí, že starší kompilátory s tím mohou mít potíže a může to být velmi těžko odhalitelná chyba. V novém C%%++%%11, již tento požadevek není, stále však zůstává pro C99.
V případě VS Code, podobně jako v celé řadě jiných programů, lze chování editor nastavit, např. [[https://stackoverflow.com/questions/44704968/visual-studio-code-insert-new-line-at-the-end-of-files|Insert New Line at the End of Files]].
Q: //Je možné umístit návěští pro příkaz ''goto'' před cyklus?//
V zásadě ano, jediným zásadním omezením je pouze v rámci jedné funkce. Dále je nutné, aby za návěštím byl příkaz, například definice proměnné není příkaz. Musí existovat adresa instrukce, na kterou má ''goto'' skočit.
^ Návěští před začátkem cyklu ^ Návěští před začátkem cyklu před definicí proměnné (**nelze**)^ Návěští před začátkem cyklu s příkazem ^
|
int a; // začátek platnosti a
outer:
for (int i = 0; i < 3; ++i) {
goto outer;
}
|
outer: // definice proměnné není příkaz
int a;
for (int i = 0; i < 3; ++i) {
goto outer;
}
|
outer: // po návěští je příkaz
;
int a;
for (int i = 0; i < 3; ++i) {
goto outer;
}
|
Nicméně podstatnou nevýhodou umístění návěští před cyklus je horší čitelnost a tím také vyšší náchylnost k chybě a zacyklení.