Prázdný ukazatel

Někdy ukazatel nemá na co ukazovat. Představte si funkci, která v poli teplot hledá první mráz, tedy teplotu pod nulou, a vrátí adresu prvku, ve kterém ho našla. Co má vrátit, když celý týden nemrzlo? K tomu má jazyk C hodnotu NULL, prázdný ukazatel: ukazatel, který nikam neukazuje.

Tato funkce vrací adresu, a proto má návratový typ int *. &cisla[i] je adresa prvku s indexem i:

int *najdi_zaporne(int *cisla, int pocet) {
    for (int i = 0; i < pocet; i++) {
        if (cisla[i] < 0) {
            return &cisla[i];
        }
    }
    return NULL;
}

Proč funkce vrací adresu, a ne rovnou teplotu? Číslem nejde říct „žádný není“: jakékoli číslo, které by funkce vrátila, by mohlo být skutečnou teplotou. Ukazatel to umí, protože NULL není adresa žádné proměnné.

Ukazatel, který může být NULL, před použitím zkontrolujte podmínkou:

#include <stdio.h>

int *najdi_zaporne(int *cisla, int pocet) {
    for (int i = 0; i < pocet; i++) {
        if (cisla[i] < 0) {
            return &cisla[i];
        }
    }
    return NULL;
}

int main(void) {
    int tyden[] = {3, 1, -2, 0, -4};
    int *mraz = najdi_zaporne(tyden, 5);
    if (mraz != NULL) {
        printf("První mráz: %d\n", *mraz);
    } else {
        printf("Žádný mráz\n");
    }
    return 0;
}

Tento kód vypíše:

První mráz: -2

Proč kontrolovat? Číst nebo zapisovat přes NULL je chyba, protože tam žádná proměnná není. Na počítači takový program obvykle spadne, často s hláškou Segmentation fault. Tady v prohlížeči čtení přes NULL zastaví program chybou RuntimeError: unreachable, stejnou jako u indexu za koncem pole. Ta neříká, co se pokazilo, a tak když ji uvidíte v programu s ukazateli, hledejte ukazatel, který může být NULL.

NULL je také dobrá počáteční hodnota pro ukazatel, který zatím nemá na co ukazovat: int *nalezeno = NULL;. Ukazatel bez hodnoty, int *p;, tady způsobí chybu při překladu, jakmile ho použijete (variable 'p' is uninitialized when used here), stejně jako každá jiná proměnná bez hodnoty.

Ještě jedno pravidlo pro funkce, které vracejí ukazatel: vracejte jen adresy věcí, které existují i po skončení funkce, třeba prvků pole, které funkce dostala. Lokální proměnné funkce po jejím skončení zaniknou, a proto jejich adresy nikdy nevracejte.

Pokyny

V poli sedadla je 1 obsazené sedadlo a 0 volné. Program se nepřeloží: když není volné žádné sedadlo, funkce najdi_volne_misto skončí bez return. Doplňte na její konec, za cyklus, return NULL;. Program pak dvakrát vypíše Rezervováno.

Do kina přichází třetí divák. V main zavolejte rezervuj(sedadla, 4); potřetí. Program dvakrát vypíše Rezervováno a pak skončí chybou RuntimeError: unreachable: řada je plná, funkce najdi_volne_misto vrátila NULL a funkce rezervuj se přes něj pokusila zapisovat. Opravte funkci rezervuj: když je misto rovno NULL, vypíše Vyprodáno a nic nezmění, jinak sedadlo rezervuje jako dosud. Program vypíše Rezervováno, Rezervováno a Vyprodáno.

Začněte programovat zdarma

Registrací souhlasíte s provozními podmínkami a zásadami ochrany osobních údajů.

Nebo se registrujte pomocí:

9/11