Funkce v programovacím jazyku C3

16. 10. 2025
Doba čtení: 38 minut

Sdílet

Programovací jazyk C3
Autor: Root.cz s využitím Zoner AI
Jednou z nejdůležitějších koncepcí (nejenom) v jazyku C3 je koncept funkcí. Začneme popisem běžných pojmenovaných funkcí, ovšem později se dostaneme i k anonymním funkcím a metodám (což jsou funkce navázané na konkrétní datové typy).

Obsah

1. Funkce v programovacím jazyku C3

2. Kontroly prováděné překladačem jazyka C3

3. Výchozí hodnoty parametrů

4. Parametry bez výchozí hodnoty musí předcházet parametry s výchozí hodnotou

5. Explicitní uvedení jmen parametrů při volání funkce

6. Pojmenování parametrů s výchozí hodnotou při volání funkce

7. Funkce s proměnným počtem parametrů

8. Realizace funkce pro výpočet součtu všech předaných hodnot

9. Předání obsahu pole do funkce s proměnným počtem parametrů

10. Pořadí předávání parametrů do funkce s proměnným počtem parametrů

11. Funkce vracející hodnotu typu Optional

12. Využití operátoru ??

13. Kontrakty v definici funkce

14. Kontrakt určující podmínku pro hodnotu parametru

15. Složitější příklad: nepřímé volání funkce s definovaným kontraktem

16. Předávání referencí (ukazatelů) do funkcí

17. Parametry označené [&out] a [&in]

18. Předávání ukazatelů typu void * do volané funkce

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. Funkce v programovacím jazyku C3

Jednou z nejdůležitějších koncepcí (nejenom) v jazyku C3 je koncept funkcí. Začneme běžnými pojmenovanými funkcemi, ovšem dostaneme se i k anonymním funkcím a metodám (což jsou funkce navázané na konkrétní datové typy). V jazyku C3 jsou funkce deklarovány s využitím klíčového slova fn, za kterým následuje typ návratové hodnoty funkce, jméno funkce a seznam typů+jmen argumentů funkce umístěný do kulatých závorek. Deklarace funkcí je tedy možné ve zdrojovém kódu velmi snadno nalézt, což do jisté míry pomáhá i překladači (dokáže jednoznačně odlišit začátek deklarace funkce od deklarace proměnné).

V dnešním prvním demonstračním příkladu je deklarována dvojice funkcí:

module functions;
import std::io;
 
fn int add(int a, int b)
{
    return a+b;
}
 
fn void main()
{
    io::printf("%d+%d=%d\n", 1, 2, add(1, 2));
}

Povšimněte si, že funkce bez parametrů má prázdné kulaté závorky. Původní „céčkový“ styl deklarace funkce bez parametrů není podporován. To si můžeme velmi snadno ověřit:

module functions;
import std::io;
 
fn int add(int a, int b)
{
    return a+b;
}
 
fn void main(void)
{
    io::printf("%d+%d=%d\n", 1, 2, add(1, 2));
}

Překlad tohoto zdrojového kódu skončí chybou:

 6:     return a+b;
 7: }
 8:
 9: fn void main(void)
                 ^^^^
(/home/ptisnovs/src/c3-examples/c3-functions/1.c3:9:14) Error: C-style
'foo(void)' style argument declarations are not valid, please remove 'void'.

2. Kontroly prováděné překladačem jazyka C3

Překladač jazyka C3 pochopitelně při volání funkcí (resp. při zápisu volání funkcí) provádí kontroly, které zjišťují, zda je použit správný počet parametrů, jestli mají parametry korektní typ, zda je splněn kontrakt (viz další text) atd. Opět si to můžeme vyzkoušet:

module functions;
import std::io;
 
fn int add(int a, int b)
{
    return a+b;
}
 
fn void main()
{
    add(1, 2);
    add(1);
    add(1, 2, 3);
 
    add(1.1, 2.2);
    add(5000000000, 5000000000);
}

Funkce add je několikrát volána se špatným počtem a/nebo typem parametrů, což překladač odhalí a vypíše poměrně dobře pochopitelná chybová hlášení:

 9: fn void main()
10: {
11:     add(1, 2);
12:     add(1);
            ^
(/home/ptisnovs/src/c3-examples/c3-functions/02_check_arguments.c3:12:9) Error:
1 more argument was expected after this one, did you forget it?
 
 1: module functions;
 2: import std::io;
 3:
 4: fn int add(int a, int b)
           ^^^
(/home/ptisnovs/src/c3-examples/c3-functions/02_check_arguments.c3:4:8) Note:
The definition was here.
 
10: {
11:     add(1, 2);
12:     add(1);
13:     add(1, 2, 3);
                  ^
(/home/ptisnovs/src/c3-examples/c3-functions/02_check_arguments.c3:13:15)
Error: This argument would exceed the number of parameters, did you add too
many arguments?
 
 1: module functions;
 2: import std::io;
 3:
 4: fn int add(int a, int b)
           ^^^
(/home/ptisnovs/src/c3-examples/c3-functions/02_check_arguments.c3:4:8) Note: The definition was here.
 
12:     add(1);
13:     add(1, 2, 3);
14:
15:     add(1.1, 2.2);
            ^^^
(/home/ptisnovs/src/c3-examples/c3-functions/02_check_arguments.c3:15:9) Error:
'double' cannot implicitly be converted to 'int', but you may use a cast.
 
13:     add(1, 2, 3);
14:
15:     add(1.1, 2.2);
16:     add(5000000000, 5000000000);
            ^^^^^^^^^^
(/home/ptisnovs/src/c3-examples/c3-functions/02_check_arguments.c3:16:9) Error:
The value '5000000000' is out of range for 'int', so you need an explicit cast
to truncate the value.

Kontrolováno jsou i návratové typy:

module functions;
import std::io;
 
fn int add(int a, int b)
{
    return a+b;
}
 
fn void main()
{
    bool x;
 
    x = add(1, 2);
}

Výsledek:

10: {
11:     bool x;
12:
13:     x = add(1, 2);
            ^^^^^^^^^
(/home/ptisnovs/src/c3-examples/c3-functions/18_check_return_type.c3:13:9)
Error: 'int' cannot implicitly be converted to 'bool', but you may use a cast.

A pochopitelně se kontroluje i počet parametrů vracených z funkce:

module functions;
import std::io;
 
fn int add(int a, int b)
{
}
 
fn void foo(int a, int b)
{
    return a+b;
}
 
fn void main()
{
}

Obě funkce addfoo vrací nesprávný počet hodnot, což překladač opět odhalí:

 1: module functions;
 2: import std::io;
 3:
 4: fn int add(int a, int b)
           ^^^
(/home/ptisnovs/src/c3-examples/c3-functions/19_check_return_values.c3:4:8)
Error: Missing return statement at the end of the function.
 
 7:
 8: fn void foo(int a, int b)
 9: {
10:     return a+b;
               ^^^
(/home/ptisnovs/src/c3-examples/c3-functions/19_check_return_values.c3:10:12)
Error: 'int' cannot implicitly be converted to 'void', but you may use a cast.

3. Výchozí hodnoty parametrů

U funkcí lze definovat i výchozí hodnoty parametrů. V takovém případě není nutné při volání funkce předávat novou hodnotu, protože se použije výchozí hodnota. Příklad s výchozí hodnotou posledního parametru b:

module functions;
import std::io;
 
fn int add(int a, int b=0)
{
    return a+b;
}
 
fn void main()
{
    io::printf("%d+%d=%d\n", 1, 0, add(1));
    io::printf("%d+%d=%d\n", 1, 2, add(1, 2));
}

Výsledky:

1+0=1
1+2=3

V další variantě mají oba parametry funkce add nastavenou výchozí hodnotu:

module functions;
import std::io;
 
fn int add(int a=0, int b=0)
{
    return a+b;
}
 
fn void main()
{
    io::printf("%d+%d=%d\n", 0, 0, add());
    io::printf("%d+%d=%d\n", 1, 0, add(1));
    io::printf("%d+%d=%d\n", 1, 2, add(1, 2));
}

To je opět zcela korektní a volání funkce bez předání parametrů, s předáním jednoho parametru i s předáním obou parametrů bude počítat hodnoty podle očekávání:

0+0=0
1+0=1
1+2=3

4. Parametry bez výchozí hodnoty musí předcházet parametry s výchozí hodnotou

Podobně, jako je tomu i u dalších programovacích jazyků, které podporují parametry s výchozí hodnotou, musí být i v jazyku C3 tyto parametry uvedeny na konci seznamu parametrů. Pokusme se tedy v definici (hlavičce) funkce nastavit výchozí hodnotu prvního parametru, ovšem nikoli parametru druhého:

module functions;
import std::io;
 
fn int add(int a=0, int b)
{
    return a+b;
}
 
fn void main()
{
    io::printf("%d+%d=%d\n", 1, 0, add(1));
    io::printf("%d+%d=%d\n", 1, 2, add(1, 2));
}

Překladač programovacího jazyka C3 v tomto případě ohlásí chybu, ovšem nikoli v definici funkce, ale až při jejím volání:

 8:
 9: fn void main()
10: {
11:     io::printf("%d+%d=%d\n", 1, 0, add(1));
                                           ^
(/home/ptisnovs/src/c3-examples/c3-functions/05_default_arguments.c3:11:40)
Error: 1 more argument was expected after this one, did you forget it?
 
 1: module functions;
 2: import std::io;
 3:
 4: fn int add(int a=0, int b)
           ^^^
(/home/ptisnovs/src/c3-examples/c3-functions/05_default_arguments.c3:4:8) Note: The definition was here.

5. Explicitní uvedení jmen parametrů při volání funkce

Při volání funkcí s běžnými (pozičními) parametry je ve skutečnosti možné tyto parametry explicitně pojmenovat, což však neumožní změnit jejich pořadí! Pochopitelně je však nutné při volání funkce tyto parametry uvést i se svým jménem. V některých programovacích jazycích se používá tento zápis:

volaná_funkce(foo=hodnota, bar=hodnota, baz=hodnota)

V jazyku C3 je zápis nepatrně odlišný:

volaná_funkce(foo:hodnota, bar:hodnota, baz:hodnota);

Příklad použití pro funkci, ve které záleží na pořadí předaných parametrů:

module functions;
import std::io;
 
fn int div(int a, int b)
{
    return a/b;
}
 
fn void main()
{
    io::printf("%d/%d=%d\n", 10, 2, div(a:10, b:2));
    io::printf("%d/%d=%d\n", 10, 3, div(a:10, b:3));
}

Výsledek:

10/2=5
10/3=3

Předání parametrů v jiném pořadí však není v C3 povoleno:

module functions;
import std::io;
 
fn int div(int a, int b)
{
    return a/b;
}
 
fn void main()
{
    io::printf("%d/%d=%d\n", 10, 2, div(b:2, a:10));
    io::printf("%d/%d=%d\n", 10, 3, div(b:3, a:10));
}

Výsledkem bude informace o dvou chybách nalezených ve zdrojovém kódu:

 8:
 9: fn void main()
10: {
11:     io::printf("%d/%d=%d\n", 10, 2, div(b:2, a:10));
                                                 ^^^^
(/home/ptisnovs/src/c3-examples/c3-functions/07_named_arguments.c3:11:46)
Error: Named arguments must always be declared in order.

 8:
 9: fn void main()
10: {
11:     io::printf("%d/%d=%d\n", 10, 2, div(b:2, a:10));
                                            ^^^
(/home/ptisnovs/src/c3-examples/c3-functions/07_named_arguments.c3:11:41) Note:
Place it before this argument.
 
 9: fn void main()
10: {
11:     io::printf("%d/%d=%d\n", 10, 2, div(b:2, a:10));
12:     io::printf("%d/%d=%d\n", 10, 3, div(b:3, a:10));
                                                 ^^^^
(/home/ptisnovs/src/c3-examples/c3-functions/07_named_arguments.c3:12:46)
Error: Named arguments must always be declared in order.
 
 9: fn void main()
10: {
11:     io::printf("%d/%d=%d\n", 10, 2, div(b:2, a:10));
12:     io::printf("%d/%d=%d\n", 10, 3, div(b:3, a:10));
                                            ^^^
(/home/ptisnovs/src/c3-examples/c3-functions/07_named_arguments.c3:12:41) Note:
Place it before this argument.
Poznámka: mohlo by se zdát, že se jedná o zbytečnou syntaxi, ovšem v dalších kapitolách uvidíme, že může být v některých případech užitečná.

6. Pojmenování parametrů s výchozí hodnotou při volání funkce

Pojmenovat je možné i parametry s výchozí hodnotou, což je kombinace obou přístupů popsaných v předchozích dvou kapitolách:

module functions;
import std::io;
 
fn int div(int a=1, int b=1)
{
    return a/b;
}
 
fn void main()
{
    io::printf("%d/%d=%d\n", 1, 1, div());
    io::printf("%d/%d=%d\n", 10, 1, div(a:10));
    io::printf("%d/%d=%d\n", 10, 2, div(a:10, b:2));
    io::printf("%d/%d=%d\n", 10, 3, div(a:10, b:3));
}

Vypočtené a zobrazené výsledky by měly vypadat následovně:

1/1=1
10/1=10
10/2=5
10/3=3

Ovšem opět není možné pořadí parametrů při volání funkce prohodit:

module functions;
import std::io;
 
fn int div(int a=1, int b=1)
{
    return a/b;
}
 
fn void main()
{
    io::printf("%d/%d=%d\n", 10, 2, div(b:2, a:10));
}

Výsledek:

 8:
 9: fn void main()
10: {
11:     io::printf("%d/%d=%d\n", 10, 2, div(b:2, a:10));
                                                 ^^^^
(/home/ptisnovs/src/c3-examples/c3-functions/1.c3:11:46) Error: Named arguments
must always be declared in order.
 
 8:
 9: fn void main()
10: {
11:     io::printf("%d/%d=%d\n", 10, 2, div(b:2, a:10));
                                            ^^^
(/home/ptisnovs/src/c3-examples/c3-functions/1.c3:11:41) Note: Place it before
this argument.

7. Funkce s proměnným počtem parametrů

V některých případech je užitečné mít možnost vytvoření funkce, která bude mít proměnný počet parametrů. Takové funkce jsou podporovány i původním jazykem C, i když práce s proměnným počtem parametrů je zde poměrně komplikovaná. Naproti tomu v jazyku C3 se s takovými funkcemi pracuje velmi snadno a při zpracování většího množství parametrů ani nemusí docházet k chybám (přístup k neexistujícímu parametru atd).

V hlavičce funkce akceptující proměnný (a předem neznámý) počet parametrů používá zápis:

typ... jméno

Například:

fn int sum(int... args)
...
...
...

V těle funkce se s args pracuje stejně, jako by se jednalo o řez (slice). To znamená, že nemusíme předávat ani počet skutečně předaných argumentů ani používat makra typu va_start (jako je tomu v jazyku C).

8. Realizace funkce pro výpočet součtu všech předaných hodnot

Pokusme se nyní o implementaci funkce, která po svém zavolání provede součet všech předaných celočíselných hodnot, přičemž není dopředu známo, kolik těchto hodnot bude ve skutečnosti předáno. Interně je součet hodnot realizován programovou smyčkou foreach, se kterou jsme se již v tomto seriálu seznámili. Povšimněte si, jak jednoduše a čitelně je celý výpočet realizován:

module functions;
import std::io;
 
fn int sum(int... args)
{
    int sum = 0;
    foreach (arg : args) {
        sum += arg;
    }
    return sum;
}
 
fn void main()
{
    io::printf("%d\n", sum());
    io::printf("%d\n", sum(1));
    io::printf("%d\n", sum(1, 2));
    io::printf("%d\n", sum(1, 2, 3));
}

Funkce sum je postupně volána bez parametrů, s jedním parametrem, se dvěma a nakonec se třemi parametry:

0
1
3
6

9. Předání obsahu pole do funkce s proměnným počtem parametrů

Do funkce akceptující proměnný počet parametrů je možné předat i obsah celého pole. Používá se přitom zápis se třemi tečkami. Po zavolání funkce (tedy v jejím těle) se řízení programu chová tak, jakoby byla funkce zavolána s tolika parametry, kolik je prvků předaného pole:

int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
io::printf("%d\n", sum(...values));
module functions;
import std::io;
 
fn int sum(int... args)
{
    int sum = 0;
    foreach (arg : args) {
        sum += arg;
    }
    return sum;
}
 
fn void main()
{
    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    io::printf("%d\n", sum());
    io::printf("%d\n", sum(1));
    io::printf("%d\n", sum(1, 2));
    io::printf("%d\n", sum(1, 2, 3));
    io::printf("%d\n", sum(...values));
}

Opět si zkontrolujme, jaké výsledky budou vypočteny a zobrazeny:

0
1
3
6
55

10. Pořadí předávání parametrů do funkce s proměnným počtem parametrů

V současné verzi programovacího jazyka C můžeme narazit na následující past, například u funkce s touto hlavičkou:

fn int sum(int... args, int multiplier)
...
...
...

Problém spočívá v tom, že při volání funkce tímto způsobem (pouhým předáním pozičních parametrů bez jejich pojmenování) nebude nikdy parametr multiplier naplněn:

io::printf("%d\n", sum());
io::printf("%d\n", sum(1));
io::printf("%d\n", sum(1, 2));
io::printf("%d\n", sum(1, 2, 3));
io::printf("%d\n", sum(...values));

To ve svém důsledku vede k tomu, že současná verze překladače jazyka C3 sice program přeloží, ale po jeho spuštění dojde k přístupu do chráněné paměti a tím pádem k segfaultu:

module functions;
import std::io;
 
fn int sum(int... args, int multiplier)
{
    int sum = 0;
    foreach (arg : args) {
        sum += arg;
    }
    return sum * multiplier;
}
 
fn void main()
{
    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    io::printf("%d\n", sum());
    io::printf("%d\n", sum(1));
    io::printf("%d\n", sum(1, 2));
    io::printf("%d\n", sum(1, 2, 3));
    io::printf("%d\n", sum(...values));
}

Oprava spočívá buď v prohození obou parametrů tak, aby args byl na konci, nebo v explicitním pojmenování parametrů při volání funkce:

io::printf("%d\n", sum(multiplier: 10));
io::printf("%d\n", sum(1, multiplier: 10));
io::printf("%d\n", sum(1, 2, multiplier: 10));
io::printf("%d\n", sum(1, 2, 3, multiplier: 10));
io::printf("%d\n", sum(...values, multiplier: 10));

Můžeme si to ostatně velmi snadno otestovat:

module functions;
import std::io;
 
fn int sum(int... args, int multiplier)
{
    int sum = 0;
    foreach (arg : args) {
        sum += arg;
    }
    return sum * multiplier;
}
 
fn void main()
{
    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    io::printf("%d\n", sum(multiplier: 10));
    io::printf("%d\n", sum(1, multiplier: 10));
    io::printf("%d\n", sum(1, 2, multiplier: 10));
    io::printf("%d\n", sum(1, 2, 3, multiplier: 10));
    io::printf("%d\n", sum(...values, multiplier: 10));
}

Tento program již bude bez problémů přeložitelný i spustitelný:

0
10
30
60
550

11. Funkce vracející hodnotu typu Optional

Připomeňme si, že v programovacím jazyku C3 je možné pracovat s hodnotami typu Optional. Ty obsahují buď konkrétní hodnotu (například celé číslo), nebo informaci o chybě resp. o neexistující hodnotě. Samozřejmě nám nic nebrání v deklaraci funkce, jejíž návratový typ bude právě Optional. Příkladem může být funkce realizující celočíselné dělení, která (jak asi správně předpokládáte) není dobře definována pro dělitel nastavený na nulu. V takovém případě by funkce měla vracet informaci o chybě a tudíž právě zde využijeme typ Optional. Návratovým typem tedy nebude pouhé int ale int?:

module functions;
import std::io;
 
faultdef ZERO_INPUT;
 
fn int? div(int a=1, int b=1)
{
    if (b==0) {
        return ZERO_INPUT?;
    }
    return a/b;
}
 
fn void main()
{
    (void)io::printf("%d/%d=%d\n", 1, 1, div());
    (void)io::printf("%d/%d=%d\n", 10, 1, div(a:10));
    (void)io::printf("%d/%d=%d\n", 10, 2, div(a:10, b:2));
    (void)io::printf("%d/%d=%d\n", 10, 3, div(a:10, b:3));
    (void)io::printf("%d/%d=%d\n", 10, 0, div(a:10, b:0));
}

Ověřme si, jak se bude tento příklad, který vlastně vůbec nepočítá s chybovou hodnotou, chovat v runtime:

1/1=1
10/1=10
10/2=5
10/3=3

To je zajímavé, protože poslední příkaz io::printf nebyl vůbec spuštěn. Je to způsobeno tím, že je před něj zapsána operace přetypování na void. Chování jazyka C3 je následující – pokud nějaká volaná funkce vrací typ Optional a namísto (obalené) hodnoty je vrácena chyba, je vyhodnocení přerušeno.

Bez přetypování nebude možné příklad vůbec přeložit:

16:     io::printf("%d/%d=%d\n", 1, 1, div());
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        (/home/ptisnovs/src/c3-examples/c3-functions/13_optional.c3:16:5) Error:
        The result of this call is optional due to its argument(s). This
        optional result may not be implicitly discarded. Please assign it to a
        variable, ignore it with '(void)', rethrow with '!' or panic with '!!'.
 
14: fn void main()
15: {
16:     io::printf("%d/%d=%d\n", 1, 1, div());
17:     io::printf("%d/%d=%d\n", 10, 1, div(a:10));
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        (/home/ptisnovs/src/c3-examples/c3-functions/13_optional.c3:17:5) Error:
        The result of this call is optional due to its argument(s). This
        optional result may not be implicitly discarded. Please assign it to a
        variable, ignore it with '(void)', rethrow with '!' or panic with '!!'.

12. Využití operátoru ??

V souvislosti s funkcemi, které vrací hodnoty typu Optional, se můžeme setkat s použitím speciálního operátoru zapisovaného dvojicí znaků ??. Tento operátor umožňuje řetězit větší množství podvýrazů, z nichž každý je typu Optional. Pokud je levý podvýraz vyhodnocen jako normální hodnota, je výsledkem zápisu levý podvýraz ?? pravý podvýraz přímo levý podvýraz. Naopak, jestliže je levý podvýraz vyhodnocen jako chybějící hodnota a/nebo chyba, je výsledkem zápisu levý podvýraz ?? pravý podvýraz podvýraz pravý.

To nám umožňuje (například) reagovat na chybu při dělení tak, že tuto chybu nahradíme hodnotou –1. Zápis je poměrně elegantní:

result = div(10, 1) ?? -1;

Vyzkoušejme si to v praxi, nyní opět s funkcí div upravenou do takové podoby, že v případě, kdy by se mělo dělit nulou, vrací chybu:

module functions;
import std::io;
 
faultdef ZERO_INPUT;
 
fn int? div(int a=1, int b=1)
{
    if (b==0) {
        return ZERO_INPUT?;
    }
    return a/b;
}
 
fn void main()
{
    int? result;
 
    result = div(10, 1) ?? -1;
    (void)io::printf("%d/%d=%d\n", 10, 1, result);
 
    result = div(10, 0) ?? -1;
    (void)io::printf("%d/%d=%d\n", 10, 0, result);
}

Takto budou vypadat výsledky:

10/1=10
10/0=-1
Poznámka: pochopitelně je možné s využitím operátoru ?? zřetězit i větší množství (pod)výrazů.

13. Kontrakty v definici funkce

V programovacím jazyku C3 nalezneme ještě jednu zajímavou konstrukci. Jedná se o takzvané kontrakty, s jejichž využitím je možné překladači předat další dodatečné informace týkající se buď parametrů funkce, nebo její návratové hodnoty. Kontrakty se tedy rozdělují na specifikaci podmínek, které je nutné splnit před voláním (resp. v rámci volání) funkce a na specifikaci podmínek, které budou platit po zavolání funkce. Striktně řečeno se nejedná o součást typového systému, ale pouze o určitá doporučení pro překladač, který se může, ale taky nemusí těmito podmínkami řídit (někdy je totiž tok programu tak složitý, že se překladač „ztratí“ a neumožní kontrolu všech zapsaných podmínek). V následujících kapitolách si ukážeme základní způsoby použití kontraktů, ovšem ve skutečnosti mohou být kontrakty i složitější (ostatně se k těm složitějším ještě vrátíme).

14. Kontrakt určující podmínku pro hodnotu parametru

Podívejme se nyní na velmi jednoduchý příklad kontraktu. S funkcí div, která dokáže vypočítat celočíselný podíl, jsme se již setkali. Nyní tuto funkci upravíme do odlišné podoby – s využitím kontraktu budeme specifikovat, že druhý parametr b nesmí být nulový. Pokud se funkce volá s předáním konstant, dokáže tento kontrakt kontrolovat již překladač:

module functions;
import std::io;
 
<*
 @require b != 0
*>
fn int div(int a, int b)
{
    return a/b;
}
 
fn void main()
{
    io::printf("%d/%d=%d\n", 10, 2, div(10, 2));
    io::printf("%d/%d=%d\n", 10, 3, div(10, 3));
    io::printf("%d/%d=%d\n", 10, 0, div(10, 0));
}

Pokus o překlad tohoto zdrojového kódu dopadne následovně:

13: {
14:     io::printf("%d/%d=%d\n", 10, 2, div(10, 2));
15:     io::printf("%d/%d=%d\n", 10, 3, div(10, 3));
16:     io::printf("%d/%d=%d\n", 10, 0, div(10, 0));
                                        ^^^^^^^^^^
(/home/ptisnovs/src/c3-examples/c3-functions/15_contract.c3:16:37)
Error: @require "b != 0" violated.

Naproti tomu v následujícím demonstračním příkladu již samotný překladač kontrakt nezajistí – to ponechá až na runtime systému:

module functions;
import std::io;
 
<*
 @require b != 0
*>
fn int div(int a, int b)
{
    return a/b;
}
 
fn void main()
{
    for (int i=10; i>=0; i--) {
        io::printf("%d/%d=%d\n", 10, i, div(10, i));
    }
}

Problém s předáním nulové hodnoty do parametru b sice stále bude nalezen, ale až v runtime, nikoli při překladu:

10/10=1
10/9=1
10/8=1
10/7=1
10/6=1
10/5=2
10/4=2
10/3=3
10/2=5
10/1=10
 
ERROR: '@require "b != 0" violated.'
  in std.core.builtin.default_panic (/home/ptisnovs/xy/c3c/build/lib/std/core/builtin.c3:175) [/home/ptisnovs/src/c3-examples/c3-functions/functions]
  in functions.main (/home/ptisnovs/src/c3-examples/c3-functions/24_contract.c3:15) [/home/ptisnovs/src/c3-examples/c3-functions/functions]
  in @main_to_void_main (/home/ptisnovs/xy/c3c/build/lib/std/core/private/main_stub.c3:18) [/home/ptisnovs/src/c3-examples/c3-functions/functions] [inline]
  in main (/home/ptisnovs/src/c3-examples/c3-functions/24_contract.c3:12) [/home/ptisnovs/src/c3-examples/c3-functions/functions]
  in __libc_start_call_main (source unavailable) [/lib64/libc.so.6]
  in __libc_start_main_alias_2 (source unavailable) [/lib64/libc.so.6]
  in _start (source unavailable) [/home/ptisnovs/src/c3-examples/c3-functions/functions]
Program interrupted by signal 4.

15. Složitější příklad: nepřímé volání funkce s definovaným kontraktem

Současná verze překladače programovacího jazyka C3 prozatím nedokáže spolehlivě v čase překladu detekovat problém v následujícím demonstračním příkladu. Zde opět voláme funkci div(10, 0) (tedy snažíme se dělit nulou), ovšem div voláme nepřímo přes jinou funkci call_div. Teoreticky by měl překladač tento stav detekovat a zobrazit chybové hlášení již při překladu, ve skutečnosti se tak však v tomto případě stane až v runtime:

module functions;
import std::io;
 
<*
 @require b != 0
*>
fn int div(int a, int b)
{
    return a/b;
}
 
fn int call_div(int a, int b)
{
    return div(a, b);
}
 
fn void main()
{
    io::printf("%d/%d=%d\n", 10, 2, call_div(10, 2));
    io::printf("%d/%d=%d\n", 10, 3, call_div(10, 3));
    io::printf("%d/%d=%d\n", 10, 0, call_div(10, 0));
}

A takto vypadá pokus o překlad a spuštění příkladu – chyba je vyhozena až v případě, že se skutečně dělí nulou:

Launching ./functions
10/2=5
10/3=3
 
ERROR: '@require "b != 0" violated.'
  in std.core.builtin.default_panic (/home/ptisnovs/xy/c3c/build/lib/std/core/builtin.c3:175) [/home/ptisnovs/src/c3-examples/c3-functions/functions]
  in functions.call_div (/home/ptisnovs/src/c3-examples/c3-functions/16_contract.c3:14) [/home/ptisnovs/src/c3-examples/c3-functions/functions]
  in functions.main (/home/ptisnovs/src/c3-examples/c3-functions/16_contract.c3:21) [/home/ptisnovs/src/c3-examples/c3-functions/functions]
  in @main_to_void_main (/home/ptisnovs/xy/c3c/build/lib/std/core/private/main_stub.c3:18) [/home/ptisnovs/src/c3-examples/c3-functions/functions] [inline]
  in main (/home/ptisnovs/src/c3-examples/c3-functions/16_contract.c3:17) [/home/ptisnovs/src/c3-examples/c3-functions/functions]
  in __libc_start_call_main (source unavailable) [/lib64/libc.so.6]
  in __libc_start_main_alias_2 (source unavailable) [/lib64/libc.so.6]
  in _start (source unavailable) [/home/ptisnovs/src/c3-examples/c3-functions/functions]
Program interrupted by signal 4.

16. Předávání referencí (ukazatelů) do funkcí

Typový systém programovacího jazyka C3 plně podporuje ukazatele, takže asi nebude překvapením, že do funkcí lze předávat i parametry typu ukazatel na T. To mj. umožňuje změnu hodnot přímo ve volané funkci. Ukažme si typický školní příklad funkce, která nastaví hodnotu, na kterou je předaný ukazatel:

module functions;
import std::io;
 
fn void set(int *p, int new_value)
{
    *p=new_value;
}
 
fn void main()
{
    int i = 0;
    io::printf("%d\n", i);
    set(&i, 42);
    io::printf("%d\n", i);
}

Po překladu a spuštění by se měly zobrazit následující dvě hodnoty naznačující, že se skutečně obsah proměnné i změnil, a to přes ukazatel:

0
42

17. Parametry označené [&out] a [&in]

V souvislosti s předáváním ukazatelů do funkcí je možné pomocí kontraktu naznačit, zda je hodnota předávaná ukazatelem (referencí) měnitelná uvnitř funkce či nikoli. Tento nebylo nutné u „běžných“ parametrů řešit, protože ty se předávají hodnotou (a tedy se vlastně vždy kopírují), ovšem ukazatele jako parametry slouží ke dvěma rozdílným účelům:

  1. Optimalizace – předání odkazy na velký blok paměti bez nutnosti jeho kopie, i když se ve funkci tento blok nemodifikuje
  2. Předání odkazem, tj. očekává se, že se hodnota bude přes ukazatel skutečně měnit

Rozlišení mezi těmito dvěma scénáři zajišťuje právě vhodně zapsaný kontrakt. Příkladem může být označení parametru typu ukazatel jako „výstupního“ parametru – hodnotu bude možné přes ukazatel modifikovat:

module functions;
import std::io;
 
<*
 @param [&out] p
*>
fn void set(int *p, int new_value)
{
    *p=new_value;
}
 
fn void main()
{
    int i = 0;
    io::printf("%d\n", i);
    set(&i, 42);
    io::printf("%d\n", i);
}

Tento demonstrační příklad lze bez problémů přeložit a spustit:

0
42

Ovšem taktéž můžeme přes kontrakt označit parametr typu ukazatel za vstupní, tj. referencovanou hodnotu nebude možné přes tento ukazatel modifikovat:

module functions;
import std::io;
 
<*
 @param [&in] p
*>
fn void set(int *p, int new_value)
{
    *p=new_value;
}
 
fn void main()
{
    int i = 0;
    io::printf("%d\n", i);
    set(&i, 42);
    io::printf("%d\n", i);
}

Pokus o zápis je detekován překladačem a zdrojový kód není možné přeložit:

 6: *>
 7: fn void set(int *p, int new_value)
 8: {
 9:     *p=new_value;
         ^
(/home/ptisnovs/src/c3-examples/c3-functions/22_in_out_params.c3:9:6) Error:
'in' parameters may not be assigned to.

18. Předávání ukazatelů typu void * do volané funkce

V programovacím jazyku C3 jsou podporovány i de facto beztypové ukazatele, které jsou typu void *. Při provádění dereference je však nutné provést explicitní přetypování, například tak, jak je to ukázáno v dnešním posledním demonstračním příkladu (což není moc pěkný zápis, na druhou stranu se však beztypové ukazatele v jazyce C3 nepoužívají příliš často):

module functions;
import std::io;
 
fn void set(void *p, int new_value)
{
    *(int*)p=new_value;
}
 
fn void main()
{
    int i = 0;
    io::printf("%d\n", i);
    set(&i, 42);
    io::printf("%d\n", i);
}

Po překladu a spuštění tohoto demonstračního příkladu by se měly zobrazit stejné zprávy, jako tomu bylo v šestnácté kapitole:

0
42

19. Repositář s demonstračními příklady

Demonstrační příklady vytvořené pro nejnovější verzi programovacího jazyka C3 byly uloženy do repositáře dostupného na adrese https://github.com/tisnik/c3-examples. Následují odkazy na jednotlivé příklady (či jejich nedokončené části).

Demonstrační příklady z prvního článku o programovacím jazyku C3:

# Příklad Stručný popis Adresa
1 factorial.c3 realizace výpočtu faktoriálu https://github.com/tisnik/c3-examples/blob/master/intro­duction/factorial.c3
2 factorial_macro.c3 výpočet faktoriálu konkrétní hodnoty implementovaný formou makra https://github.com/tisnik/c3-examples/blob/master/intro­duction/factorial_macro.c3
       
3 swap_macro.c3 makro realizující prohození dvou hodnot https://github.com/tisnik/c3-examples/blob/master/intro­duction/swap_macro.c3
       
4 renderer.c výpočet a vykreslení Juliovy množiny implementovaný v jazyku C https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer.c
5 renderer_v1.c3 definice datové struktury s rozměry rastrového obrázku a skeleton všech funkcí https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v1.c3
6 renderer_v2.c3 anotace parametrů funkcí typu ukazatel (pointer) https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v2.c3
7 renderer_v3.c3 statická kontrola, zda se nepředávají neinicializované ukazatele https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v3.c3
8 renderer_v4.c3 runtime kontrola, zda se nepředávají neinicializované ukazatele https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v4.c3
9 renderer_v5.c3 první (nekorektní) varianta funkce pro inicializaci barvové palety https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v5.c3
10 renderer_v6.c3 druhá (korektní) varianta funkce pro inicializaci barvové palety https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v6.c3
11 renderer_v7.c3 volání knihovní I/O funkce a volání nativní céčkovské funkce https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v7.c3
12 renderer_v8.c3 plně funkční program pro výpočet a vykreslení Juliovy množiny https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v8.c3

Demonstrační příklady ze druhého článku o jazyku C3:

# Příklad Stručný popis Adresa
13 01_just_main.c3 struktura nejjednoduššího programu obsahujícího pouze prázdnou funkci main https://github.com/tisnik/c3-examples/blob/master/c3-basics/01_just_main.c3
14 02_module_name.c3 struktura programu s uvedeným plným jménem modulu https://github.com/tisnik/c3-examples/blob/master/c3-basics/02_module_name.c3
15 03_hello_world.c3 klasický program typu „Hello, world!“ napsaný v jazyku C3 https://github.com/tisnik/c3-examples/blob/master/c3-basics/03_hello_world.c3
16 04_exit_value.c3 ukončení procesu s předáním návratového kódu zpět volajícímu programu https://github.com/tisnik/c3-examples/blob/master/c3-basics/04_exit_value.c3
17 05_c_function.c3 zavolání funkce definované v knihovně programovacího jazyka C https://github.com/tisnik/c3-examples/blob/master/c3-basics/05_c_function.c3
       
18 06_bool_type.c3 definice proměnných typu pravdivostní hodnota (bool) https://github.com/tisnik/c3-examples/blob/master/c3-basics/06_bool_type.c3
19 07_int_to_bool.c3 implicitní převod hodnoty typu int na pravdivostní hodnotu (nekorektní řešení) https://github.com/tisnik/c3-examples/blob/master/c3-basics/07_int_to_bool.c3
20 08_int_to_bool.c3 explicitní převod hodnoty typu int na pravdivostní hodnotu (korektní řešení) https://github.com/tisnik/c3-examples/blob/master/c3-basics/08_int_to_bool.c3
21 09_int_to_bool.c3 explicitní převod hodnoty typu int na pravdivostní hodnotu (nekorektní řešení) https://github.com/tisnik/c3-examples/blob/master/c3-basics/09_int_to_bool.c3
22 10_bool_sizeof.c3 zjištění velikosti paměti obsazené hodnotou typu bool https://github.com/tisnik/c3-examples/blob/master/c3-basics/10_bool_sizeof.c3
       
23 11_int_types.c3 definice proměnných typu celé číslo se znaménkem s různou bitovou šířkou https://github.com/tisnik/c3-examples/blob/master/c3-basics/11_int_types.c3
24 12_uint_types.c3 definice proměnných typu celé číslo bez znaménka s různou bitovou šířkou https://github.com/tisnik/c3-examples/blob/master/c3-basics/12_uint_types.c3
25 13_no_suffixes.c3 celočíselné konstanty bez uvedení suffixu (bitové šířky) https://github.com/tisnik/c3-examples/blob/master/c3-basics/13_no_suffixes.c3
26 14_suffixes.c3 celočíselné konstanty s uvedením sufficu (bitové šířky) https://github.com/tisnik/c3-examples/blob/master/c3-basics/14_suffixes.c3
27 15_int_sizeof.c3 zjištění velikosti paměti obsazené celočíselnými hodnotami se znaménkem https://github.com/tisnik/c3-examples/blob/master/c3-basics/15_int_sizeof.c3
28 16_uint_sizeof.c3 zjištění velikosti paměti obsazené celočíselnými hodnotami bez znaménka https://github.com/tisnik/c3-examples/blob/master/c3-basics/16_uint_sizeof.c3
29 17_int_conversions.c3 korektní převody mezi celočíselnými hodnotami s různou bitovou šířkou https://github.com/tisnik/c3-examples/blob/master/c3-basics/17_int_conversions.c3
30 18_int_conversions.c3 nekorektní převody mezi celočíselnými hodnotami s různou bitovou šířkou https://github.com/tisnik/c3-examples/blob/master/c3-basics/18_int_conversions.c3
31 19_int_conversions.c3 explicitní převody a přetečení hodnot https://github.com/tisnik/c3-examples/blob/master/c3-basics/19_int_conversions.c3
       
32 20_float_types.c3 definice proměnných typu numerická hodnota s plovoucí řádovou čárkou (tečkou) https://github.com/tisnik/c3-examples/blob/master/c3-basics/20_float_types.c3
       
33 21_vector_type.c3 definice vektoru obsahujícího celočíselné hodnoty https://github.com/tisnik/c3-examples/blob/master/c3-basics/21_vector_type.c3
34 22_vector_operations.c3 základní operace s celými vektory https://github.com/tisnik/c3-examples/blob/master/c3-basics/22_vector_operations.c3
35 23_vector_sizes.c3 zjištění a tisk velikosti vektorů (různé datové typy prvků vektorů, shodná délka) https://github.com/tisnik/c3-examples/blob/master/c3-basics/23_vector_sizes.c3
36 24_vector_sizes.c3 zjištění a tisk velikosti vektorů (stejné datové typy prvků vektorů, odlišná délka) https://github.com/tisnik/c3-examples/blob/master/c3-basics/24_vector_sizes.c3

Demonstrační příklady použité ve třetím článku o jazyku C3:

# Příklad Stručný popis Adresa
37 01_vector_type.c3 definice vektoru, modifikace prvků vektoru, tisk obsahu celého vektoru https://github.com/tisnik/c3-examples/blob/master/c3-containers/01_vector_type.c3
38 02_vector_parameter.c3 předání vektoru do funkce hodnotou https://github.com/tisnik/c3-examples/blob/master/c3-containers/02_vector_parameter.c3
39 03_vector_pointer.c3 předání vektoru do funkce odkazem (přes ukazatel) https://github.com/tisnik/c3-examples/blob/master/c3-containers/03_vector_pointer.c3
       
40 04_array_type.c3 definice pole, modifikace prvků pole, tisk obsahu celého pole https://github.com/tisnik/c3-examples/blob/master/c3-containers/04_array_type.c3
41 05_array_parameter.c3 předání pole do funkce hodnotou https://github.com/tisnik/c3-examples/blob/master/c3-containers/05_array_parameter.c3
42 06_array_pointer.c3 předání pole do funkce odkazem (přes ukazatel) https://github.com/tisnik/c3-examples/blob/master/c3-containers/06_array_pointer.c3
       
43 07_slice_type.c3 vytvoření (konstrukce) řezu (slice) https://github.com/tisnik/c3-examples/blob/master/c3-containers/07_slice_type.c3
44 08_slice_parameter.c3 předání řezu do funkce https://github.com/tisnik/c3-examples/blob/master/c3-containers/08_slice_parameter.c3
45 09_slice_slicing.c3 konstrukce řezu z pole stejně pojmenovanou operací (řez od..do) https://github.com/tisnik/c3-examples/blob/master/c3-containers/09_slice_slicing.c3
46 10_slice_slicing.c3 konstrukce řezu z pole stejně pojmenovanou operací (záporné indexy) https://github.com/tisnik/c3-examples/blob/master/c3-containers/10_slice_slicing.c3
47 11_slice_slicing.c3 konstrukce řezu z pole stejně pojmenovanou operací (určení délky řezu) https://github.com/tisnik/c3-examples/blob/master/c3-containers/11_slice_slicing.c3
48 12_slice_of_slice.c3 konstrukce řezu z jiného řezu https://github.com/tisnik/c3-examples/blob/master/c3-containers/12_slice_of_slice.c3
       
49 13_list_type.c3 vytvoření (konstrukce) seznamu https://github.com/tisnik/c3-examples/blob/master/c3-containers/13_list_type.c3
50 14_list_parameter.c3 předání seznamu do funkce https://github.com/tisnik/c3-examples/blob/master/c3-containers/14_list_parameter.c3
       
51 15_dynamic_array.c3 vytvoření (konstrukce) dynamicky alokovaného pole https://github.com/tisnik/c3-examples/blob/master/c3-containers/15_dynamic_array.c3
       
52 16_string_type.c3 základní typ řetězce string https://github.com/tisnik/c3-examples/blob/master/c3-containers/16_string_type.c3
53 17_string_unicode.c3 Unicode znaky v řetězci typu string https://github.com/tisnik/c3-examples/blob/master/c3-containers/17_string_unicode.c3
54 18_zstring_type.c3 řetězce ukončené nulou (C-string, ASCIIZ) https://github.com/tisnik/c3-examples/blob/master/c3-containers/18_zstring_type.c3
55 19_zstring_unicode.c3 Unicode znaky v řetězci typu zstring https://github.com/tisnik/c3-examples/blob/master/c3-containers/19_zstring_unicode.c3
56 20_string_comparison.c3 porovnávání obsahu řetězců https://github.com/tisnik/c3-examples/blob/master/c3-containers/20_string_comparison.c3

Demonstrační příklady ze čtvrtého o jazyku C3:

# Příklad Stručný popis Adresa
57 01_program_stub.c3 struktura programu s uvedeným plným jménem modulu https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/01_program_stub.c3
       
58 02_if.c3 nejjednodušší forma rozvětvení založené na konstrukci if https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/02_if.c3
59 03_if_else.c3 plné rozvětvení realizované konstrukcí if-else https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/03_if_else.c3
60 04_improper_if.c3 nekorektní způsob zápisu programové konstrukce if-else (porovnání s jazykem C) https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/04_improper_if.c3
61 05_improper_if.c3 nekorektní způsob zápisu programové konstrukce if-else (porovnání s jazykem C) https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/05_improper_if.c3
62 06_if_else_if.c3 složitější rozvětvení založené na programové konstrukci if-else if-else https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/06_if_else_if.c3
       
63 07_switch_basic.c3 základní forma vícenásobného rozvětvení založeného na konstrukci switch-case https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/07_switch_basic.c3
64 08_switch_basic.c3 větší množství podmínek a programová konstrukce switch-case https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/08_switch_basic.c3
65 09_switch_condition.c3 podmínky zapsané ve větvích programové konstrukci switch-case vyhodnocované v čase běhu procesu https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/09_switch_condition.c3
66 10_switch_true.c3 konstrukce switch-case bez uvedeného výrazu za klíčovým slovem switch https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/10_switch_true.c3
67 11_switch_break.c3 zápis prázdné větve default v programové konstrukci switch-case https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/11_switch_break.c3
68 12_switch_nextcase.c3 pokračování ve vykonávání konstrukce switch-case vynucené klíčovým slovem nextcase https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/12_switch_nextcase.c3
       
69 13_for_loop.c3 základní forma programové smyčky realizované klíčovým slovem for https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/13_for_loop.c3
70 14_foreach_loop.c3 základní forma programové smyčky typu for-each https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/14_foreach_loop.c3
71 15_foreach_loop.c3 programová smyčka for-each vracející index prvku i hodnotu prvku https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/15_foreach_loop.c3
72 16_foreach_loop.c3 modifikace obsahu pole v programové smyčce for-each https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/16_foreach_loop.c3
73 17_foreach_loop.c3 pokus o modifikaci obsahu procházeného pole https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/17_foreach_loop.c3
74 18_foreach_loop.c3 modifikace procházeného pole přes ukazatel na prvek https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/18_foreach_loop.c3
75 19_foreach_r_loop.c3 programová smyčka for-each, ve které se sekvencí prochází v opačném pořadí https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/19_foreach_r_loop.c3
       
76 20_while_loop.c3 základní forma programové smyčky typu while https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/20_while_loop.c3
77 21_while_loop2.c3 programová smyčka typu while s konstrukcí break https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/21_while_loop2.c3
78 22_nested_loops.c3 realizace vnořených programových smyček https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/22_nested_loops.c3
79 23_break.c3 vnořené programové smyčky a příkaz break: ukončení vnitřní smyčky https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/23_break.c3
80 24_break.c3 vnořené programové smyčky a příkaz break: ukončení vnější smyčky https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/24_break.c3
81 25_break.c3 vnořené programové smyčky a příkaz break, varianta se smyčkami typu while https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/25_break.c3

Demonstrační příklady z pátého článku o jazyku C3:

# Příklad Stručný popis Adresa
82 01_regular_variable.c3 definice běžné proměnné typu int, přístup k hodnotě této proměnné https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/01_regular_variable.c3
83 02_optional_value.c3 definice proměnné typu Optional int, pokus o přímý přístup k hodnotě této proměnné (nekorektní varianta) https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/02_optional_value.c3
84 03_optional_value.c3 korektní čtení proměnné typu Optional int s detekcí chyby https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/03_optional_value.c3
85 04_optional_value.c3 korektní čtení proměnné typu Optional int s detekcí chyby https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/04_optional_value.c3
86 05_fault.c3 uživatelsky definovaný typ nesoucí informaci o chybě https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/05_fault.c3
87 06_fault.c3 uživatelsky definovaný typ nesoucí informaci o chybě https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/06_fault.c3
88 07_force_unwrap.c3 použití operátoru !! (force unwrap) https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/07_force_unwrap.c3
89 08_force_unwrap.c3 použití operátoru !! (force unwrap) https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/08_force_unwrap.c3
       
90 09_factorial.c3 běžný výpočet faktoriálu bez reakce na neplatný vstup https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/09_factorial.c3
91 10_factorial.c3 výpočet faktoriálu s reakcí na neplatný vstup – řešení bez kontroly návratové hodnoty https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/10_factorial.c3
92 11_factorial.c3 výpočet faktoriálu s reakcí na neplatný vstup – řešení s kontrolou návratové hodnoty https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/11_factorial.c3
       
93 12_defer_basic_usage.c3 konstrukce defer v programovacím jazyce C3 https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/12_defer_basic_usage.c3
94 13_more_defers.c3 pořadí provádění příkazů v blocích defer https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/13_more_defers.c3
95 14_defer_scope.c3 konstrukce defer definovaná ve vnitřních blocích v jazyce C3 https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/14_defer_scope.c3
96 15_defer_return.c3 konstrukce defer a return https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/15_defer_return.c3
       
97 16_init_finalize.c3 funkce označené jako @init a @finalizer https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/16_init_finalize.c3
       
98 defer.go konstrukce defer v programovacím jazyce Go https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/defer.go
99 defer_scope.go konstrukce defer definovaná ve vnitřních blocích v jazyce Go https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/defer_scope.go

A konečně následují odkazy na demonstrační příklady z článku dnešního:

# Příklad Stručný popis Adresa
100 01_regular_function.c3 deklarace běžných funkcí v jazyku C3 https://github.com/tisnik/c3-examples/blob/master/c3-functions/01_regular_function.c3
101 02_check_arguments.c3 kontrola parametrů předávaných do funkce překladačem jazyka C3 https://github.com/tisnik/c3-examples/blob/master/c3-functions/02_check_arguments.c3
       
102 03_default_arguments.c3 funkce s jedním parametrem, který má nastavenou výchozí hodnotu a jedním běžným parametrem (korektní pořadí parametrů) https://github.com/tisnik/c3-examples/blob/master/c3-functions/03_default_arguments.c3
103 04_default_arguments.c3 funkce se všemi parametry s nastavenu výchozí hodnotou https://github.com/tisnik/c3-examples/blob/master/c3-functions/04_default_arguments.c3
104 05_default_arguments.c3 funkce s jedním parametrem, který má nastavenou výchozí hodnotu a jedním běžným parametrem (nekorektní pořadí parametrů) https://github.com/tisnik/c3-examples/blob/master/c3-functions/05_default_arguments.c3
       
105 06_named_arguments.c3 explicitní uvedení jmen parametrů při volání funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/06_named_arguments.c3
106 07_named_arguments.c3 explicitní uvedení jmen parametrů při volání funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/07_named_arguments.c3
107 08_named_default_arguments.c3 pojmenování parametrů s výchozí hodnotou při volání funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/08_named_default_ar­guments.c3
       
108 09_sum.c3 realizace funkce pro výpočet součtu všech předaných hodnot https://github.com/tisnik/c3-examples/blob/master/c3-functions/09_sum.c3
109 10_sum.c3 předání obsahu pole do funkce s proměnným počtem parametrů https://github.com/tisnik/c3-examples/blob/master/c3-functions/10_sum.c3
110 11_varargs.c3 pořadí předávání parametrů do funkce s proměnným počtem parametrů (nekorektní způsob použití) https://github.com/tisnik/c3-examples/blob/master/c3-functions/11_varargs.c3
111 12_varargs.c3 pořadí předávání parametrů do funkce s proměnným počtem parametrů (korektní způsob použití) https://github.com/tisnik/c3-examples/blob/master/c3-functions/12_varargs.c3
       
112 13_optional.c3 funkce vracející hodnotu typu Optional https://github.com/tisnik/c3-examples/blob/master/c3-functions/13_optional.c3
113 14_optional.c3 využití operátoru ?? https://github.com/tisnik/c3-examples/blob/master/c3-functions/14_optional.c3
       
114 15_contract.c3 kontrakty uvedené u funkcí https://github.com/tisnik/c3-examples/blob/master/c3-functions/15_contract.c3
115 16_contract.c3 kontrakty uvedené u funkcí https://github.com/tisnik/c3-examples/blob/master/c3-functions/16_contract.c3
       
116 17_c_declaration.c3 deklarace funkce bez parametrů „céčkovým způsobem“ (nekorektní zápis) https://github.com/tisnik/c3-examples/blob/master/c3-functions/17_c_declaration.c3
117 18_check_return_type.c3 kontrola návratové hodnoty překladačem jazyka C3 https://github.com/tisnik/c3-examples/blob/master/c3-functions/18_check_return_type.c3
118 19_check_return_value.c3 kontrola počtu návratových hodnot překladačem jazyka C3 https://github.com/tisnik/c3-examples/blob/master/c3-functions/19_check_return_value.c3
119 20_in_out_params.c3 předání ukazatelů do volané funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/20_in_out_params.c3
120 21_in_out_params.c3 označení ukazatelů kontrakty [in] a [out] https://github.com/tisnik/c3-examples/blob/master/c3-functions/21_in_out_params.c3
121 22_in_out_params.c3 označení ukazatelů kontrakty [in] a [out] https://github.com/tisnik/c3-examples/blob/master/c3-functions/22_in_out_params.c3
122 23_void_pointer.c3 předávání ukazatelů typu void * do volané funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/23_void_pointer.c3

20. Odkazy na Internetu

  1. Programovací jazyk C3: evoluce, nikoli revoluce
    https://www.root.cz/clanky/pro­gramovaci-jazyk-c3-evoluce-nikoli-revoluce/
  2. Programovací jazyk C3: datové typy pro moderní architektury
    https://www.root.cz/clanky/pro­gramovaci-jazyk-c3-datove-typy-pro-moderni-architektury/
  3. Programovací jazyk C3: složené datové typy a kontejnery
    https://www.root.cz/clanky/pro­gramovaci-jazyk-c3-slozene-datove-typy-a-kontejnery/
  4. The C3 Programming Language
    https://c3-lang.org/
  5. C3 For C Programmers
    https://c3-lang.org/language-overview/primer/
  6. C3 is a C-like language trying to be an incremental improvement over C rather than a whole new language
    https://www.reddit.com/r/Pro­grammingLanguages/comments/o­ohij6/c3_is_a_clike_langu­age_trying_to_be_an/
  7. Tiobe index
    https://www.tiobe.com/tiobe-index/
  8. PYPL PopularitY of Programming Language
    https://pypl.github.io/PYPL.html
  9. C3 Tutorial
    https://learn-c3.org/
  10. History of programming languages
    https://devskiller.com/history-of-programming-languages/
  11. History of programming languages (Wikipedia)
    https://en.wikipedia.org/wi­ki/History_of_programming_lan­guages
  12. D language
    https://dlang.org/
  13. Zig programming language
    https://ziglang.org/
  14. V language
    https://vlang.io/
  15. D programming language
    https://en.wikipedia.org/wi­ki/D_(programming_language)
  16. Zig programming language (Wikipedia)
    https://en.wikipedia.org/wi­ki/Zig_(programming_langu­age)
  17. V programming language (Wikipedia)
    https://en.wikipedia.org/wi­ki/V_(programming_language)
  18. Syntax highlighting for C3's programming language
    https://github.com/Airbus5717/c3.vim
  19. Go factorial
    https://gist.github.com/e­simov/9622710
  20. Generational list of programming languages
    https://en.wikipedia.org/wi­ki/Generational_list_of_pro­gramming_languages
  21. The Language Tree: Almost Every Programming Language Ever Made
    https://github.com/Phileo­sopher/langmap
  22. List of C-family programming languages
    https://en.wikipedia.org/wi­ki/List_of_C-family_programming_languages
  23. Compatibility of C and C++
    https://en.wikipedia.org/wi­ki/Compatibility_of_C_and_C%2B%2B
  24. C++23: compatibility with C
    https://www.sandordargo.com/blog/2023/08/23/cpp­23-c-compatibility
  25. Can C++ Run C Code? Understanding Language Compatibility
    https://www.codewithc.com/can-c-run-c-code-understanding-language-compatibility/
  26. C3: Comparisons With Other Languages
    https://c3-lang.org/faq/compare-languages/
  27. C3 Programming Language Gains Traction as Modern C Alternative
    https://biggo.com/news/202504040125_C3_Pro­gramming_Language_Alterna­tive_to_C
  28. The case against a C alternative
    https://c3.handmade.networ­k/blog/p/8486-the_case_against_a_c_alternative
  29. C (programming language) Alternatives
    https://alternativeto.net/software/c-programming-language-/
  30. Seriál Programovací jazyk Go
    https://www.root.cz/seria­ly/programovaci-jazyk-go/
  31. Is C3 the Underdog That Will Overtake Zig and Odin?
    https://bitshifters.cc/2025/05/22/c3-c-tradition.html
  32. „Hello, World!“ program
    https://en.wikipedia.org/wi­ki/%22Hello%2C_World!%22_pro­gram
  33. The C Programming Language
    https://en.wikipedia.org/wi­ki/The_C_Programming_Langu­age
  34. Kontejner (abstraktní datový typ)
    https://cs.wikipedia.org/wi­ki/Kontejner_(abstraktn%C3%AD_da­tov%C3%BD_typ)
  35. Are arrays not considered containers because they are not based off of a class?
    https://stackoverflow.com/qu­estions/37710975/are-arrays-not-considered-containers-because-they-are-not-based-off-of-a-class
  36. Array declaration (C, C++)
    https://en.cppreference.com/w/cpp/lan­guage/array.html
  37. Understanding the Apple ‘goto fail;’ vulnerability
    https://www.blackduck.com/blog/un­derstanding-apple-goto-fail-vulnerability-2.html
  38. Branch (computer science)
    https://en.wikipedia.org/wi­ki/Branch_(computer_scien­ce)
  39. Conditional (computer programming)
    https://en.wikipedia.org/wi­ki/Conditional_(computer_pro­gramming)
  40. Dangling else
    https://en.wikipedia.org/wi­ki/Dangling_else
  41. Switch statement
    https://en.wikipedia.org/wi­ki/Switch_statement
  42. Compiler correctness
    https://en.wikipedia.org/wi­ki/Compiler_correctness
Neutrální ikona do widgetu na odběr článků ze seriálů

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.


Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.