Praktické postřehy přednášejícího na MFF UK:
F
unkce, které vrací hodnoty změnou globálních parametrů: "To je jako když vám někdo má umýt okna, a on u toho ještě zhasne a namydlí schody."
"Pascal, to je taková maminka. Všude jsou zaoblený rohy, nízkonapěťový zásuvky, a když upadnete, tak do měkkýho. To se musíte hodně snažit, abyste si ublížili".

"V céčku se všude válej otevřený břitvy. Takže můžete všechno, ale musíte vědět, že když uděláte takle (posunek naznačující podříznutí krku), tak končíte."

Všeobecná pravidla pro psaní kódu v "C"
Upozornění: Tento dokument vystavený na Internetu je přesnou kopií vnitřního dokumentu z 27.2.2019. Proto v něm je tolik polámaných odkazů.


Účel  - dosáhnout co nejlepších výsledků při programování procesoru. Tyto výsledky jsou:



Vlastnosti jazyka - proč právě 'C'

Požadavky

Programovací jazyk musí umožňovat:
Další žádoucí vlastnosti: Těmto požadavkům vyhovuje jen 'C'. Jeho další velkou výhodou je robustnost, konzistence daná H-soubory a dobrý výhled do budoucnosti:

Podstata jazyka

Program v 'C' je pouhá hromada funkcí, globálních proměnných a prototypů, ovládaná příkazy preprocesoru C. Je to jednoduché a účinné.

Kompilátor C s následným linkerem vlastně pouze obsazují daty blok paměti. Program a data jsou v něm umístěny podle rozmyslu kompilátoru a linkeru, správný start programu se uskutečňuje skokem na místo bloku, kde je umístěna 1. instrukce programu. Další chod programu je určen vlastnostmi procesoru. Ten pracuje tak dlouho, dokud narazí:
Počítač naprogramovaný v 'C' lze přirovnat k lidskému tělu: Toto srovnání ukazuje, že v programovacím jazyku mají své místo globální proměnné i příkaz goto - jen je třeba umět je správně používat.


C a ostatní jazyky

Ostatní jazyky sice mají různé nástroje:

ale toto vše se nechá udělat i v 'C' a přitom zachovat transparentnost kódu.


Porozumění paměťovým modelům


Nalezeno na https://www.viva64.com/en/a/0050/

Od samého počátku vývoje počítačů bylo jasné, že čím více paměti a čím rychlejší procesor, tím lepší bude počítač. Velikost paměti prvních počítačů byla omezována jejich cenou, takže se vyskytovaly velikosti 4KB, 8KB, 16KB, 32KB i 64KB. První počítače se 64KB stály několik milionů korun, zabíraly plochu malého sálu, pracovaly nepřetržitě a obsluhovalo je asi deset lidí.

Přelom přišel s vynálezy IBM: diskové paměti, polovodičové paměti a stavebnice zvaná IBM PC, která používala 1MB paměti. Z té doby pochází výrok jednoho počítačového odborníka, že 1MB paměti je maximum, které bude kdy moci běžný uživatel využít.
V té době se také začalo mluvit o paměťových modelech. Ty vycházejí z toho, že paměťové adresy i délky paměťových objektů jsou čísla v rozsahu:

Příslušné paměťové modely jsou:



Použitý model

Vytvořeno na základě porovnání stavu Windows 32bit, Windows 64bit a Linux 64bit. Viz též https://www.viva64.com/en/a/0004/#ID0EVQCK .
Model pracuje tak, že:

Tak všechno pracuje jak třeba, pro Windows jsou nastaveny projekty v kompilátorech, pro Linux vše běží automaticky.

Podrobnější popis:




size_t


ptrdiff_t


Kódování konstant a literálů
Dokud bude možno využívat MSCV 6.0 je mechanizmus práce navržen takto:
Případný přechod na jiný kompilátor by neměl být moc těžký:

Praktické programování

Vlastnosti a nedostatky MSVC 6.0

Velké programy a namespaces

Velkým programem se rozumí program s vnořenými balíky třetích stran. V takovém případě se může objevit problém duplicitních jmen nebo jmen neodpovídajících standardu tohoto dokumentu. Aby byla zajištěna transparentnost systému, je třeba:



Linux

Dokumentace  - vyrábí se podle potřeby ve více stupních:

Formátování kódu - mělo by být zvoleno a dodržováno pečlivě autorem. Hlavní požadavky jsou: jednoduchost, srozumitelnost a čitelnost kódu.


Psaní kódu - Požadavkem je: přehlednost, jednoduchost, srozumitelnost a čitelnost kódu. Tedy ne "chytré" konstrukce, které jsou jednak zdrojem chyb, jednak jiný programátor má spoustu práce s jejich luštěním a nakonec je stejně přepíše .

Projekty

Jsou uloženy v adresáři D:\111, jejich popis je uveden vždy v modulu, ve kterém se nachází vstupní bod programu.


Kompilace
Předpokládá se v prostředí MSVC 6.0, K-Develop, CodeWarrior, VC 10+ a Dev-C++. Nepoužívají se optimalizace kódu - zejména v MSVC 6.0. Z hlediska přenositelnosti se programové moduly dělí na:

.H soubory - doporučuje se nevnořovat je - předejde se tak vícenásobnému vkládání .H souborů a všelijakým cyklům. Hlavní modul programu má obsahovat všechny .H soubory. Tím je dáno jejich bezkonfliktní pořadí, které potom může být použito v kterémkoli dalším modulu.


Modularizace

Modularizace zjednodušuje a zpřehledňuje programování a také je oporou dokumentace.

Konfigurace 'C' projektů

Je na samostatné stránce.


Globální proměnné


Statické proměnné  - pojmenovávají se static_...      - jsou jen v jednom .CPP, nejsou v .H - patrně jsou zbytečné, je lepší použít globální

Globální i statické proměnné mohou mít nežádoucí vliv při vícenásobném volání funkce. Musí se tedy používat tak, aby bylo kdykoli možno zkontrolovat jejich použití - buď vyhledáním v kódu nebo speciálním programem.



Makra - pojmenovávají se MACRO_...  - použijí se tam, kde to zpřehlední kód a kudy není potřeba procházet při


Error management
Je na samostatné stránce.


Literálový systém

Tento systém slouží pro uložení literálů mimo program do souborů *.CDB:


Výstupní zařízení


Debug management


CGI programování v C

Vytvoření každé procedury má tři kroky:
  1. Vytvoření vstupního bodu někde na HTML stránce, pro tuto aplikaci je vstupní bod na stránce http://194.108.109.100/c%82love%82k/ve%82da/matematika/index.htm - je tam odkaz Testovací aplikace odkazující na /scripts/client.exe?m=form_new&p=105&p1=CS - číslo 105 je komunikační identifikátor, CS označuje, že formulář má být v češtině.
  2. Vytvoření formuláře s položkami pro zadávání parametrů procedury (provádí se v modulu ins_fmi.cpp) - formulář testovací procedury vyrábí (v našem případě) funkce FORM_for_test_application().
    Prototyp této funkce musí přijít do vhodného *.H souboru a její volání se dá do větvicí rutiny v ins_fmi.cpp.
  3. Vytvoření odpovědi ze parametrů zadaných uživatelem - tuto odpověď vyrábí funkce Evaluate_test_application(). Prototyp této funkce musí přijít do vhodného *.H souboru a její volání se dá do větvicí rutiny v ins_fmo.cpp.
    Ověžení procedury se dělá takto:
    1. Spustí se Apache (pokud již neběží)
    2. Spustí se vytvořený program v debug módu
    3. Spustí se browser a:


Kopírování kódu do HTML stránek

Volá se rutina podle vzoru INET_ShowSource(output_CB, "DB_math.cpp", "Quadratic",  START);
- ta podle posledního parametru zapíše heading or footing of code listing

V kódu se používají dvojice direktiv podle vzoru:
#define INET_SHOW__Quadratic
#undef INET_SHOW__Quadratic



Kopírování JavaSciptu do HTML stránek

Volá se rutina podle vzoru INET_CopySource(output_CB, "Ziva_citanka.htm", "CSS2");

V HTML kódu se používají dvojice direktiv podle vzoru:
<script INET_COPY__CSS2 START></script>
<script INET_COPY__CSS2 STOP></script>
Každý jeden příkaz INET_CopySource() musí kopírovat celistvé bloky JavaScriptu vmezené příkazy <script ...> ... </script>.


Různá pravidla

Efekty týmové práce

Výuka
Výuku lze rozdělit na:


Odkazy
 
Zdrojové texty

HASHTABLE program in C

Nalezeno na http://www.tutorialspoint.com/data_structures_algorithms/hash_table_program_in_c.htm . Ukázka čisté a efektivní práce. Na tom serveru je i pískoviště v pro C.


#include
<stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> #define SIZE 20 struct DataItem { int data; int key; }; struct DataItem* hashArray[SIZE]; struct DataItem* dummyItem; struct DataItem* item; int hashCode(int key){ return key % SIZE; } struct DataItem *search(int key){ //get the hash int hashIndex = hashCode(key); //move in array until an empty while(hashArray[hashIndex] != NULL){ if(hashArray[hashIndex]->key == key) return hashArray[hashIndex]; //go to next cell ++hashIndex; //wrap around the table hashIndex %= SIZE; } return NULL; } void insert(int key,int data){ struct DataItem *item = (struct DataItem*) malloc(sizeof(struct DataItem)); item->data = data; item->key = key; //get the hash int hashIndex = hashCode(key); //move in array until an empty or deleted cell while(hashArray[hashIndex] != NULL && hashArray[hashIndex]->key != -1){ //go to next cell ++hashIndex; //wrap around the table hashIndex %= SIZE; } hashArray[hashIndex] = item; } struct DataItem* delete(struct DataItem* item){ int key = item->key; //get the hash int hashIndex = hashCode(key); //move in array until an empty while(hashArray[hashIndex] != NULL){ if(hashArray[hashIndex]->key == key){ struct DataItem* temp = hashArray[hashIndex]; //assign a dummy item at deleted position hashArray[hashIndex] = dummyItem; return temp; } //go to next cell ++hashIndex; //wrap around the table hashIndex %= SIZE; } return NULL; } void display(){ int i = 0; for(i = 0; i<SIZE; i++) { if(hashArray[i] != NULL) printf(" (%d,%d)",hashArray[i]->key,hashArray[i]->data); else printf(" ~~ "); } printf("\n"); } int main(){ dummyItem = (struct DataItem*) malloc(sizeof(struct DataItem)); dummyItem->data = -1; dummyItem->key = -1; insert(1, 20); insert(2, 70); insert(42, 80); insert(4, 25); insert(12, 44); insert(14, 32); insert(17, 11); insert(13, 78); insert(37, 97); display(); item = search(37); if(item != NULL){ printf("Element found: %d\n", item->data); }else { printf("Element not found\n"); } delete(item); item = search(37); if(item != NULL){ printf("Element found: %d\n", item->data); }else { printf("Element not found\n"); } }

If we compile and run the above program then it would produce following result −

Output

 ~~  (1,20)  (2,70)  (42,80)  (4,25)  ~~  ~~  ~~  ~~  ~~  ~~  ~~ (12,44)  (13,78)  (14,32)  ~~  ~~  (17,11)  (37,97)  ~~ 
Element found: 97
Element not found

 

Naivní parser programu v 'C'
 
Spíše nepovedené dílo v přelomu 2017/2018, které mělo usnadnit v té době probíhající zavedení GLO_CB do celého programu. Nakonec se vše provedlo ručně. Vstupní rutina modulu je  Fix_2017_12_25()  


Program přečte vstupní soubor a určí zda je to .cpp nebo .h