Co je neplatné v c. Co je void main(void). Jednoduchý příklad funkce v C

Štítky: void*, prázdné ukazatele, nedefinované ukazatele.

Ukazatele typu void

V C existuje speciální typ ukazatele - void ukazatele nebo prázdné ukazatele. Tyto ukazatele se používají, když není znám typ proměnné. Protože void nemá typ, operace zrušení adresy (převzetí obsahu) a aritmetika adresy na něj nejsou použitelné, protože reprezentace dat je neznámá. Pokud však pracujeme s ukazatelem typu void, pak jsou nám k dispozici porovnávací operace.

Pokud potřebujete pracovat s nulovým ukazatelem, musíte nejprve explicitně přetypovat typ. Například

#zahrnout #zahrnout int main() ( void *p = NULL; int intVar = 10; char charVar = "A"; float floatVar = 24,3; float *floatPtr = NULL; p = *((int*) p) = 20; printf(" intVar = %d\n", intVar); p = printf("charVar = %c\n", *((char*) p)); p = floatPtr = (float*) p; printf("floatVar = % .3f", *floatPtr); getch(); )

Proměnná nemůže být typu void tento typ je definován pouze pro ukazatele. Byly nalezeny prázdné ukazatele široké uplatnění při volání funkcí. Můžete napsat funkci obecný účel, který bude fungovat s jakýmkoliv typem. Napišme například funkci swap, která prohodí obsah dvou proměnných. Tato funkce bude mít tři argumenty – ukazatele na proměnné, které je třeba prohodit, a jejich velikost.

#zahrnout #zahrnout #zahrnout #zahrnout void swap(void *a, void *b, size_t size) ( char* tmp; //vytvoří dočasnou proměnnou pro výměnu tmp = (char*) malloc(size); memcpy(tmp, a, size); memcpy(a , b, velikost memcpy(b, tmp, velikost); unsigned long f = 3ll printf("a = %.3f, b = %.3f\n", a, b, sizeof(float) = %.3f, b = %.3f\n", a,; b printf("c = %.3f, d = %.3f\n", c, d, sizeof( double)); .3f\n", c, d); printf("e = %ld, f = %ld \n", e, f); &e, &f, sizeof(unsigned long)); printf("e = %ld , f = %ld \n", e, f);

Naše funkce může vypadat jinak. Obejdeme se bez drahé alokace paměti a kopírujeme bajt po bajtu.

Void swap(void *a, void *b, velikost_t velikost) ( char tmp; velikost_t i; pro (i = 0; i< size; i++) { tmp = *((char*) b + i); *((char*) b + i) = *((char*) a + i); *((char*) a + i) = tmp; } }

Nulové ukazatele umožňují vytvářet funkce, které vracejí a přijímají stejné parametry, ale mají jiné jméno. To se bude hodit později při studiu ukazatelů funkcí. Například

Int cmpInt(void* a, void* b) ( return *((int*) a) - *((int*) b); ) int cmpString(void *a, void* b) ( return strcmp((char*) ) a, (char*) b ) int cmpFloat(void* a, void* b) ( float fdiff = *((float*) a) - *((float*) b); if (fabs(fdiff)< 0.000001f) { return 0; } if (fdiff < 0) { return -1; } else { return 1; } }

Výukový program Ru-Cyrl 18 Sypačov S.S. 1989-04-14 [e-mail chráněný]Štěpán Sypačov studentů

Stále to není jasné? – dotazy pište do schránky

V lekci 1 jste vytvořili několik programů C++. V té době bylo vaším cílem porozumět procesu tvorby a kompilace programů v C++, ne rozumět příkazům C++. V této lekci se nejprve blíže podíváte na příkazy, které tvoří program v C++. Zjistíte, že většina programů C++ má stejný formát: počínaje jedním nebo více příkazy #.zahrnout, obsahovat řetězec void main(void),a pak sadu příkazů seskupených mezi levou a pravou složenou závorku. Jak uvidíte v tomto tutoriálu, tyto poněkud zastrašující operátory lze ve skutečnosti velmi snadno zvládnout. Do konce tuto lekci Naučíte se následující základní pojmy:

  • operátor # zahrnout poskytuje výhody použití hlavičkové soubory, které obsahují příkazy C++ nebo definice programů.
  • Hlavní část programu C++ začíná příkazem void main(void).
  • Programy se skládají z jedné nebo více funkcí, které se zase skládají z příkazů určených k řešení konkrétního problému.
  • Při tisku na obrazovku budou vaše programy široce využívat výstupní proud cout.

Když píšete programy v C++, ve skutečnosti pracujete z hlediska operátoři, ale ne návod. Později budete studovat operátor přiřazení, který přiřazuje hodnoty proměnným, operátor -li, který umožňuje programu přijímat rozhodnutí atd. Prozatím budeme obsah vašeho programu označovat jako provozovatelé programů.


PODÍVEJTE SE NA PROGRAMOVÉ OPERÁTORY

V lekci 1 jste vytvořili program C++ FIRST.CPP, který obsahoval následující příkazy:

#zahrnout

void main (void)

{
cout<< «Учимся программировать на языке С++!»;
}

V tomto případě program obsahuje tři příkazy. Kudrnaté rovnátka (tzv seskupení znaků) operátoři související se skupinou:

#zahrnout

void hlavní (neplatný)

{
cout<< «Учимся программировать << «на языке С++!»;
}

V další části jsou podrobněji popsány jednotlivé příkazy programu.

PŘEDSTAVENÍ OBSLUZE #zahrnout

Každý program uvedený v lekci 1 začíná následujícím prohlášením # zahrnout:

#zahrnout

Když píšete programy v C++, těžíte z operátorů a definic, které vám kompilátor poskytuje. Při sestavování programu operátor # zahrnout způsobí, že kompilátor zahrne obsah daného souboru na začátek vašeho programu. V tomto případě kompilátor zahrne obsah souboru iostream.h.

Soubory s příponou h, které zahrnete na začátek (nebo titul) se nazývají váš program hlavičkové soubory. Pokud se podíváte na adresář obsahující soubory kompilátoru, najdete podadresář s názvem INCLUDE, který obsahuje různé hlavičkové soubory. Každý hlavičkový soubor obsahuje definice poskytnuté kompilátorem pro různé operace. Existuje například hlavičkový soubor, který obsahuje definice pro matematické operace, další hlavičkový soubor, který popisuje operace se soubory a tak dále.

Soubory záhlaví jsou soubory ASCII, takže jejich obsah můžete vytisknout na obrazovku nebo na tiskárnu. O obsah hlavičkových souborů se zatím nestarejte. Stačí pochopit, že operátor # zahrnout umožňuje používat tyto soubory. Všechny C++ programy, které vytvoříte v této knize, obsahují # příkazů. zahrnout, které byste měli používat ve svých programech.

C++ hlavičkové soubory

Každý C++ program, který vytvoříte, začíná jedním nebo více příkazy #include. Tyto příkazy říkají kompilátoru, aby zahrnul obsah daného souboru (souboru hlavičky) do vašeho programu, jako by program obsahoval příkazy, které byly v souboru include. Soubory záhlaví obsahují definice používané kompilátorem pro různé typy operací. Existují hlavičkové soubory, které definují C++ I/O operace, systémové funkce (jako jsou funkce, které vracejí aktuální datum a čas) a mnoho dalšího.

Soubory záhlaví, stejně jako programy C++, jsou soubory ASCII, jejichž obsah můžete zobrazit nebo vytisknout. Chcete-li lépe porozumět obsahu hlavičkových souborů, věnujte chvíli tisku hlavičkového souboru IOSTREAM.H, jehož obsah budete používat v každém programu C++, který napíšete. Soubor záhlaví IOSTREAM.H je obvykle umístěn v podadresáři s názvem INCLUDE, který je umístěn v adresáři obsahujícím soubory kompilátoru C++. K zobrazení a tisku obsahu souborů záhlaví použijte textový editor.

Poznámka: Nikdy neměňte obsah souborů záhlaví. To může vést k chybám při kompilaci v každém programu, který vytvoříte.

CO JE neplatný hlavní (neplatný)

Když vytvoříte program C++, váš zdrojový soubor bude obsahovat mnoho příkazů. Jak se při studiu dozvíte, pořadí, ve kterém se příkazy objevují v programu, nemusí být pořadí, ve kterém budou příkazy provedeny při spuštění programu. Každý program v C++ má jeden vstup, od kterého začíná provádění programu - hlavní program. V programech C++ operátor void main (void) označuje počáteční bod vašeho programu.

Jak budou vaše programy větší a složitější, rozdělíte je na několik malých, snadno ovladatelných částí. V tomto případě operátor void main (void) označuje počáteční (neboli hlavní) příkazy programu - část programu, která je spuštěna jako první.

Úvod do hlavního programu

Zdrojové soubory C++ mohou obsahovat mnoho příkazů. Když se program spustí, příkaz void main(void) definuje hlavní program obsahující první příkaz, který se má provést. Vaše programy v C++ by měly vždy obsahovat jeden a pouze jeden příkaz s názvem main.

Když se díváte na velké programy C++, hledejte main, abyste identifikovali příkazy, které zahajují provádění programu.

Používání prázdnota

Jak se váš program stává složitějším, měli byste jej rozdělit na menší, snáze ovladatelné části, tzv funkcí. Funkce je jednoduchá sada příkazů v programu, která provádí konkrétní úkol. Pokud jste například vytvářeli program platebních dokladů, můžete vytvořit funkci s názvem plat výpočet mezd zaměstnanců. Podobně, pokud byste psali matematický program, můžete vytvořit funkce tzv odmocnina nebo krychle které vracejí výsledek určitých matematických operací. Pokud váš program používá funkci, funkce provede svůj úkol a poté vrátí programu svůj výsledek.

Každá funkce ve vašem programu má jedinečný název. A každý program má alespoň jednu funkci. Každý program z lekce 1 měl pouze jednu pojmenovanou funkci hlavní. Lekce 9 poskytuje podrobnější přehled funkcí. Prozatím mějte na paměti, že funkce se skládá z několika souvisejících příkazů, které provádějí konkrétní úkol.

Při prozkoumávání různých programů C++ budete neustálečelit slovu prázdnota. Programy používají slovo prázdnota k označení, že funkce nevrací hodnotu nebo jí nebyly předány žádné hodnoty. Pokud například používáte prostředí MS-DOS nebo UNIX, může se program ukončit a vrátit operačnímu systému hodnotu stavu, kterou lze ověřit pomocí příkazového souboru. Dávkové soubory systému MS-DOS kontrolují stav výstupu programu pomocí příkazu IF ERRORLEVEL. Předpokládejme například program s názvem MZDY. EXE skončí s jednou z následujících hodnot stavu výstupu v závislosti na výsledku zpracování:

Uvnitř dávkového souboru MS-DOS můžete zkontrolovat výstup programu pomocí příkazu IF ERRORLEVEL:

VÝPLATNÍ PÁSKA

POKUD CHYBA ÚROVEŇ 0 POKUD NE ÚROVNĚ CHYBY 1 PŘEJÍT ÚSPĚŠNĚ
IF ERRORLEVEL 1 IF NOT ERRORLEVEL 2 GOTO NO_FILE
POKUD CHYBA ÚROVEŇ 2 POKUD NE ÚROVEŇ CHY 3 PŘEJÍT NA NO_PAPER
REM Následují další příkazy

Většina jednoduchých C++ programů, které vytvoříte v této knize, nevrátí do operačního systému žádný stavový výstup. Proto musíte slovo umístit prázdnota před hlavní jak je uvedeno níže:

void hlavní (neplatný) //- ——-> Program nevrací hodnotu

V následujících lekcích se dozvíte, že vaše programy mohou používat informace (jako je název souboru), které uživatel zadá na příkazovém řádku při spuštění programu. Pokud program nepoužívá informace z příkazového řádku, měli byste umístit slovo prázdnota v závorkách za hlavní jak je uvedeno níže:

zrušit hlavní( prázdno) //———————-> Program nepoužívá argumenty příkazového řádku

Jak se vaše programy stávají složitějšími, mohou vracet hodnoty do operačního systému nebo používat parametry příkazového řádku. Zatím však jen používat prázdno v operátor s hlavní jak je uvedeno v tomto programu.

POHLED OPERÁTORŮ SESKUPENÍ ( )

Jak se vaše programy stávají složitějšími, bude existovat jedna sada příkazů, které musí počítač provést určitý počet opakování, a další sada příkazů, které musí počítač provést, pokud je splněna určitá podmínka. V prvním případě může počítač provést stejnou sadu příkazů 100krát a přidat testovací body pro 100 studentů. Ve druhém případě může počítač zobrazit jednu zprávu, pokud všichni studenti test projdou, a další zprávu, pokud jeden nebo více studentů neuspěje. Ve svých programech C++ budete používat pravé a levé složené závorky () k seskupování souvisejících příkazů. V jednoduchých programech uvedených v prvních několika lekcích knihy tyto symboly seskupují výroky, které odpovídají výrokům ve vašem hlavním programu.

POUŽÍVÁNÍ cout PRO ZOBRAZENÍ VÝSTUPU NA OBRAZOVCE

Všechny programy C++, které jste vytvořili v lekci 1, vytiskly zprávy na obrazovku. Chcete-li zobrazit zprávu, použité programy cout a znaménko dvakrát menší než (<<), как показано ниже:

cout<< «Привет, C++!»;

Slovo coutpředstavujevýstupní proud,které C++ přiřadí standardnímu výstupnímu zařízení operačního systému. Ve výchozím nastavení operační systém přiřadí standardní výstupní zařízení obrazovce displeje. Chcete-li vytisknout zprávu na obrazovku, jednoduše použijte symbol dvojitého menšího než (nazývaný operátor vkládání) s výstupním proudemcout.V lekci 3 se naučíte, že můžete použít operátor vkládání k předávání symbolů, čísel a dalších znaků na obrazovku.

Pohled na výstupní proud cout

Už víte, že programy C++ používají výstupní proud cout k zobrazení zpráv na obrazovce. Když používáte cout k zobrazení zpráv, představte si cout jako proud znaků, které operační systém zobrazuje na obrazovce. Jinými slovy, pořadí, ve kterém váš program posílá znaky do cout, určuje pořadí znaků, které se objeví na obrazovce. Například pro následující programová prohlášení:

cout<< «Это сообщение появляется первым,»;
cout<< » а за ним следует настоящее сообщение.»;

Operační systém vypíše proud znaků následovně:

Tato zpráva se zobrazí jako první a poté skutečná zpráva.

Operátor vložení (<<) называется так, потому что позволяет вашей программе вставлять символы в выходной поток.

Již víte, že výstupní proud je cout výchozí nastavení, aby odpovídalo vaší obrazovce. Jinými slovy, když vaše programy odesílají výstup do cout, výstup se objeví na obrazovce. Pomocí operátorů přesměrování výstupu operačního systému však můžete odeslat výstup programu na tiskárnu nebo do souboru. Například následující příkaz instruuje systém MS-DOS, aby nasměroval výstup programu FIRST.EXE na tiskárnu, nikoli na obrazovku:

C:\>PRVNÍ>PRN

Jak se dozvíte v lekci 3, pomocí cout V C++ můžete tisknout znaky, celá čísla, jako je 1001, a čísla s plovoucí desetinnou čárkou, jako je 3,12345. V lekci 8 se dozvíte, že v C++ existuje také vstupní proud tzv cin, které mohou vaše programy používat ke čtení vstupu z klávesnice.

CO POTŘEBUJEŠ VĚDĚT

Tato lekce probírala některé běžné problémy, se kterými se setkáte v programech C++. V lekci 3 se naučíte používat couvat pro výstupní znaky, celá čísla a hodnoty s plovoucí desetinnou čárkou. Dozvíte se také, jak formátovat výstup. Před studiem lekce 3 se ujistěte, že jste zvládli následující základní pojmy:

  1. Většina programů v C++ začíná operátorem # zahrnout, který instruuje kompilátor, aby zahrnul obsah daného hlavičkového souboru do programu.
  2. Soubory záhlaví obsahují definice poskytnuté kompilátorem, které mohou používat vaše programy.
  3. Zdrojový soubor se může skládat z mnoha příkazů; operátor void main (void) označuje začátek hlavního programu, který obsahuje první příkaz programu, který se má provést.
  4. Jak se váš program stává složitějším, budete související příkazy seskupovat do malých, snadno ovladatelných částí nazývaných funkce. Seskupte příkazy programu pomocí pravých a levých složených závorek ().
  5. Většina programů C++ používá výstupní proud cout pro zobrazení informací na obrazovce; pomocí operátorů I/O přesměrování operačního systému však můžete přesměrovat výstup cout do souboru, zařízení (jako je tiskárna) nebo z něj dokonce udělat vstup jiného programu.

Jaké funkce se používají v C?

Funkce v C se používají k provádění specifických akcí v rámci obecného programu. Programátor sám rozhoduje, které akce se ve funkcích zobrazí. Obzvláště vhodné je použití funkcí pro opakované akce.

Jednoduchý příklad funkce v C

Příklad funkce v C:

#zahrnout #zahrnout int main(void) ( puts("Funkce v C"); return EXIT_SUCCESS; )

Jedná se o velmi jednoduchý C program. Jednoduše vytiskne řádek "Funkce v C". Program má jedinou funkci nazvanou main. Podívejme se na tuto funkci podrobně. V hlavičce funkce, tzn. v souladu

int je návratový typ funkce;

main je název funkce;

(void) je seznam argumentů funkce. Slovo void označuje, že funkce nemá žádné argumenty;

return je příkaz, který ukončí provádění funkce a vrátí výsledek funkce do bodu, ve kterém byla funkce volána;

EXIT_SUCCESS je hodnota rovna nule. Je definován v souboru stdlib.h;

část funkce za záhlavím, uzavřená ve složených závorkách

{
puts("Funkce v C");
return EXIT_SUCCESS;
}

se nazývá tělo funkce.

Když tedy pracujeme s funkcí, musíme uvést název funkce, pro nás je to hlavní, typ hodnoty vrácené funkcí, pro nás je to int, za znakem v závorce uveďte seznam argumentů jméno funkce, nemáme žádné argumenty, takže zapíšeme void, provedeme v těle funkce nějaké akce (kvůli kterým byla funkce vytvořena) a vrátíme výsledek funkce pomocí příkazu return. Zde jsou základy, které potřebujete vědět o funkcích v C.

Jak volat jinou funkci z jedné funkce v C?

Podívejme se na příklad volání funkcí v C:

/* Autor: @author Subbotin B.P..h> #include int main(void) ( puts("Funkce v C"); int d = 1; int e = 2; int f = suma(d, e); printf("1 + 2 = %d", f); return EXIT_SUCCESS)

Spustíme to a dostaneme:

Tento příklad vytvoří funkci součtu, která sečte dvě celá čísla a vrátí výsledek. Podívejme se podrobně na strukturu této funkce.

hlavička součtové funkce:

int součet (int a, int b)

zde int je návratový typ funkce;

součet je název funkce;

(int a, int b) - v závorce za názvem funkce je seznam jejích argumentů: první argument je int a, druhý argument je int b. Názvy argumentů jsou formální, tzn. Při volání funkce nemusíme posílat hodnoty proměnných s názvem a a b jako argumenty této funkci. V hlavní funkci voláme součtovou funkci takto: sum(d, e);. Je však důležité, aby argumenty předané funkci odpovídaly typu deklarovanému ve funkci.

V těle součtové funkce, tzn. Uvnitř složených závorek za hlavičkou funkce vytvoříme lokální proměnnou int c, přiřadíme jí hodnotu součtu a plus b a vrátíme ji jako výsledek funkce s příkazem return.

Nyní se podívejme, jak se funkce součtu volá z hlavní funkce.

Zde je hlavní funkce:

Int main(void) ( puts("Funkce v C"); int d = 1; int e = 2; int f = suma(d, e); printf("1 + 2 = %d", f); return EXIT_SUCCESS;

Nejprve vytvoříme dvě proměnné int

Int d = 1; int e = 2;

Předáme je součtové funkci jako hodnoty argumentů.

int f = suma(d, e);

jeho hodnota bude výsledkem součtové funkce, tzn. zavoláme funkci součtu, která vrátí hodnotu typu int, kterou přiřadíme proměnné f. Předáme d a f jako argumenty. Ale v hlavičce funkce sum

int součet (int a, int b)

argumenty se nazývají a a b, proč tedy předáme d a f? Protože v hlavičce funkce se zapisují formální argumenty, tzn. Názvy argumentů NEJSOU důležité, ale jejich typy jsou důležité. Funkce sum má oba argumenty typu int, což znamená, že při volání této funkce musíte předat dva argumenty typu int s libovolnými názvy.

Ještě jedna jemnost. Funkce musí být deklarována před jejím prvním voláním. V našem příkladu se stalo toto: nejprve je deklarována funkce součtu a poté ji voláme z hlavní funkce. Pokud je funkce deklarována za místem, kde je volána, měl by být použit prototyp funkce.

Funkční prototyp v C

Podívejme se na příklad funkce v C:

/* Autor: @author Subbotin B.P..h> #include int suma(int a, int b); int main(void) ( puts("Funkce v C"); int d = 1; int e = 2; int f = suma(d, e); printf("1 + 2 = %d", f); return EXIT_SUCCESS ) int suma(int a, int b) ( int c = 0; c = a + b; return c; )

V tomto příkladu je součtová funkce definována níže, kde je volána v hlavní funkci. V tomto případě musíte použít prototyp funkce součtu. Náš prototyp je deklarován nad hlavní funkcí:

int suma(int a, int b);

Prototyp je záhlaví funkce, které končí středníkem. Prototyp je deklarace funkce, která bude definována níže. To je přesně to, co jsme udělali: deklarovali jsme funkční prototyp

int f = suma(d, e);

a pod hlavní funkcí definujeme funkci součtu, která byla dříve deklarována v prototypu:

Int součet(int a, int b) ( int c = 0; c = a + b; návrat c; )

Jak se liší deklarace funkce v C od definice funkce v C?

Když píšeme prototyp funkce, například takto:

int suma(int a, int b);

pak deklarujeme funkci.

A když implementujeme funkci, tzn. Zapisujeme nejen název, ale i tělo funkce, například:

Int součet(int a, int b) ( int c = 0; c = a + b; návrat c; )

pak definujeme funkci.

návratový výpis

Příkaz return ukončí funkci v C a vrátí výsledek její operace do bodu volání. Příklad:

Int součet(int a, int b) ( int c = 0; c = a + b; návrat c; )

Tuto funkci lze zjednodušit:

Int součet(int a, int b) ( return a + b; )

zde příkaz return vrátí hodnotu součtu a + b.

V jedné funkci může být několik příkazů return. Příklad:

Int sum(int a, int b) ( if(a > 2) ( return 0;// První případ; ) if(b< 0) { return 0;// Второй случай; } return a + b; }

Pokud je v příkladu hodnota argumentu a větší než dva, pak funkce vrátí nulu (první případ) a vše pod komentářem „// První případ;“ nebude provedena. Pokud a je menší než dva, ale b je menší než nula, pak funkce dokončí svou práci a vše pod komentářem „// Druhý případ;“ nebude provedena.

A pouze pokud nejsou splněny obě předchozí podmínky, pak provádění programu dosáhne posledního příkazu return a vrátí se součet a + b.

Předávání argumentů funkce hodnotou

Argumenty lze předávat funkci C podle hodnoty. Příklad:

/* Autor: @author Subbotin B.P..h> #include int sum(int a) ( return a += 5; ) int main(void) ( puts("Funkce v C"); int d = 10; printf("součet = %d\n", suma(d)) ; printf("d = %d", d);

V příkladu ve funkci main vytvoříme proměnnou int d = 10. Tuto proměnnou předáme hodnotou do funkce sum(d). Uvnitř součtové funkce se hodnota proměnné zvýší o 5. Ale v hlavní funkci se hodnota d nezmění, protože byla předána hodnotou. To znamená, že byla předána hodnota proměnné, nikoli samotná proměnná. Svědčí o tom výsledek programu:

těch. po návratu ze součtové funkce se hodnota d nezměnila, zatímco uvnitř součtové funkce ano.

Předávání ukazatelů C funkce

Pokud předáte ukazatel na tuto proměnnou jako argument funkci místo hodnoty proměnné, pak se hodnota této proměnné může změnit. Například převezmeme program z předchozí části a mírně jej změníme:

/* Autor: @author Subbotin B.P..h> #include int sum(int *a) ( return *a += 5; ) int main(void) ( puts("Funkce v C"); int d = 10; printf("součet = %d\n", sum(&d )); printf("d = %d", d);

V této verzi programu jsem přešel z předávání argumentu hodnotou na předávání ukazatele na proměnnou. Pojďme se na tento bod podívat blíže.

printf("soucet = %d\n", sum(&d));

To, co je předáno součtové funkci, není hodnota proměnné d rovna 10, ale adresa této proměnné, jako je tato:

Nyní se podívejme na funkci součtu:

Int součet(int *a) ( return *a += 5; )

Jeho argument je ukazatel na int. Víme, že ukazatel je proměnná, jejíž hodnota je adresa nějakého objektu. Adresa proměnné d je odeslána do funkce součtu:

Uvnitř součtu je ukazatel int *a dereferencován. To nám umožňuje přejít od ukazatele k samotné proměnné, na kterou ukazuje náš ukazatel. A v našem případě je to proměnná d, tzn. výraz

je ekvivalentní s výrazem

Výsledek: funkce součtu změní hodnotu proměnné d:

Tentokrát se hodnota d po návratu ze součtu změní, což nebylo dodrženo v předchozím odstavci, když jsme předali argument hodnotou.

C/C++ v Eclipse

Všechny příklady pro tento článek jsem vytvořil v Eclipse. Jak pracovat s C/C++ můžete vidět v Eclipse. Pokud pracujete v jiném prostředí, příklady budou fungovat i tam.

Štítky: Funkce v C, prototyp, popis, definice, volání. Formální parametry a skutečné parametry. Argumenty funkce, předávání hodnotou, předávání ukazatelem. Návratová hodnota.

Úvod

Čím více studujeme C, tím větší jsou programy. Všechny akce shromažďujeme do jedné hlavní funkce a tytéž akce několikrát zkopírujeme, čímž vytvoříme desítky proměnných s jedinečnými názvy. Naše programy bobtnají a jsou čím dál méně srozumitelné, větve se prodlužují a větví.

Ale z této situace existuje východisko! Nyní se naučíme vytvářet funkce v C. Funkce zaprvé pomohou oddělit duplicitní kód do samostatných podprogramů, zadruhé pomohou logicky rozdělit program na části a zatřetí, funkce v C mají mnoho funkcí spojených s nimi, které umožní použití nových přístupů ke strukturování aplikací.

Funkce je pojmenovaná část programu, kterou lze opakovaně volat z jiné části programu (ve které je funkce viditelná). Funkce může mít pevný nebo proměnný počet argumentů nebo nemůže mít žádné argumenty. Funkce může buď vrátit hodnotu, nebo být prázdná (neplatná) a nevrací nic.

Mnoho funkcí již známe a víme, jak je volat - jsou to funkce knihoven stdio, stdlib, string, conio atd. Main je navíc také funkcí. Od ostatních se liší pouze tím, že je vstupním bodem při spouštění aplikace.
Funkce v C je definována v globálním kontextu. Syntaxe funkce: (, ...) ( )

Nejjednodušším příkladem je funkce, která vezme plovoucí číslo a vrátí druhou mocninu tohoto čísla

#zahrnout #zahrnout float sqr(float x) ( float tmp = x*x; return tmp; ) void main() ( printf("%.3f", sqr(9.3f)); getch(); )

Uvnitř funkce sqr jsme vytvořili lokální proměnnou, které byla přiřazena hodnota argumentu. Číslo 9.3 bylo předáno funkci jako argument. Servisní slovo return vrací hodnotu proměnné tmp. Funkci můžete přepsat následovně:

Float sqr(float x) ( return x*x; )

V tomto případě se nejprve provede násobení a poté se vrátí hodnota. Pokud funkce nic nevrátí, návratový typ bude neplatný. Například funkce, která vytiskne druhou mocninu čísla:

Void printSqr(float x) ( printf("%d", x*x); return; )

v tomto případě návrat znamená ukončení funkce. Pokud funkce nic nevrací, pak return není třeba psát. Poté funkce dokončí své dokončení a řízení se vrátí k volající funkci.

Void printSqr(float x) ( printf("%d", x*x); )

Pokud funkce nebere žádné argumenty, závorky zůstanou prázdné. Můžete také napsat slovo void:

Void printHelloWorld() ( printf("Ahoj světe"); )

ekvivalent

Void printHelloWorld(void) ( printf("Ahoj světe"); )

Formální a skutečné parametry

Při deklaraci funkce jsou specifikovány formální parametry, které jsou následně použity v rámci samotné funkce. Když voláme funkci, používáme skutečné parametry. Skutečnými parametry mohou být proměnné libovolného vhodného typu nebo konstanty.

Řekněme například, že existuje funkce, která vrací druhou mocninu čísla, a funkce, která sečte dvě čísla.

#zahrnout #zahrnout //Formální parametry mají jména a a b //pomocí nich přistupujeme k předávaným argumentům uvnitř funkce int sum(int a, int b) ( return a+b; ) float square(float x) ( return x*x; ) void main() ( //Skutečné parametry mohou mít libovolný název, včetně noname int one = 1; float two = 2.0; //Předejte proměnné, druhá proměnná je přetypována na požadovaný typ printf("%d\n" , sum(one, two) //Předávání číselných konstant printf("%d\n", sum(10, 20)); ("%d\n ", sum(10, 20.f) //Proměnná typu integer je převedena na typ s plovoucí desetinnou čárkou printf("%.3f\n", square(one)); Jako argument lze také použít volání funkce, které vrátí požadovanou hodnotu printf("%.3f\n", square(sum(2 + 4, 3)));

Vezměte prosím na vědomí, že přetypování probíhá implicitně a pouze tehdy, je-li to možné. Pokud funkce obdrží jako argument číslo, pak jí nelze předat proměnný řetězec, například „20“ atd. Obecně je lepší vždy použít správný typ nebo typ explicitně přetypovat na požadovaný.
Pokud funkce vrátí hodnotu, nemusí být uložena. Použijeme například funkci getch, která přečte znak a vrátí jej.

#zahrnout #zahrnout void main() ( char c; do ( //Uložení návratové hodnoty do proměnné c = getch(); printf("%c", c); ) while(c != "q"); //Návrat hodnota není uložena getch();

Předávání argumentů

Při předávání argumentů se zkopírují. To znamená, že jakékoli změny, které funkce provede v proměnných, probíhají pouze v rámci funkce. Například

#zahrnout #zahrnout void change(int a) ( a = 100; printf("%d\n", a); ) void main() ( int d = 200; printf("%d\n", d); change(d) printf("%d", d);

Zobrazí se programy
200
100
200
Je jasné proč. Uvnitř funkce pracujeme s proměnnou x, která je kopií proměnné d. Změníme lokální kopii, ale samotná proměnná d se nezmění. Po ukončení funkce bude lokální proměnná zničena. Proměnná d se nijak nezmění.
Jak potom můžete změnit proměnnou? Chcete-li to provést, musíte předat adresu této proměnné. Přepišme funkci tak, aby akceptovala ukazatel typu int

#zahrnout #zahrnout void change(int *a) ( *a = 100; printf("%d\n", *a); ) void main() ( int d = 200; printf("%d\n", d); změna (&d); printf("%d", d);

Nyní výstupy programu
200
100
100
Zde byla také vytvořena lokální proměnná, ale jelikož byla adresa předána, změnili jsme hodnotu proměnné d pomocí její adresy v RAM.

V programování se první způsob předávání parametrů nazývá předávání hodnotou, druhý - předávání ukazatelem. Pamatujte na jednoduché pravidlo: pokud chcete změnit proměnnou, musíte funkci předat ukazatel na tuto proměnnou. Chcete-li tedy změnit ukazatel, musíte předat ukazatel na ukazatel atd. Napišme například funkci, která vezme velikost pole typu int a vytvoří ji. Na první pohled by funkce měla vypadat nějak takto:

#zahrnout #zahrnout #zahrnout void init(int *a, velikost bez znaménka) ( a = (int*) malloc(size * sizeof(int)); ) void main() ( int *a = NULL; init(a, 100); if (a = = NULL) ( printf("CHYBA"); ) else ( printf("V pořádku..."); free(a); ) getch();

Tato funkce však vydá ERROR. Předali jsme adresu proměnné. Uvnitř funkce init byla vytvořena lokální proměnná a, která ukládá adresu pole. Po ukončení funkce byla tato lokální proměnná zničena. Kromě toho, že jsme nemohli dosáhnout požadovaného výsledku, jsme objevili únik paměti: paměť byla alokována na haldě, ale již neexistuje proměnná, která by ukládala adresu této oblasti.

Chcete-li změnit objekt, musíte na něj předat ukazatel, v tomto případě ukazatel na ukazatel.

#zahrnout #zahrnout #zahrnout void init(int **a, velikost bez znaménka) ( *a = (int*) malloc(velikost * sizeof(int)); ) void main() ( int *a = NULL; init(&a, 100); if ( a == NULL) ( printf("CHYBA"); ) else ( printf("V pořádku..."); free(a); ) getch();

Nyní vše funguje jak má.
Další podobný příklad. Pojďme napsat funkci, která vezme řetězec jako argument a vrátí ukazatel na oblast paměti, do které byl tento řetězec zkopírován.

#zahrnout #zahrnout #zahrnout #zahrnout char* initByString(const char *str) ( char *p = (char*) malloc(strlen(str) + 1); strcpy(p, str); return p; ) void main() ( char *test = initByString( "Ahoj světe!"); printf("%s", test);

V tomto příkladu nedochází k nevracení paměti. Alokovali jsme paměť pomocí funkce malloc, zkopírovali jsme tam řetězec a pak vrátili ukazatel. Lokální proměnné byly odstraněny, ale testovací proměnná ukládá adresu části paměti na hromadu, takže ji lze odstranit pomocí funkce free.

Deklarace funkce a definice funkce. Vytvoření vlastní knihovny

V C můžete deklarovat funkci před jejím definováním. Deklarace funkce, její prototyp, se skládá z návratové hodnoty, názvu funkce a typu argumentů. Názvy argumentů lze vynechat. Například

#zahrnout #zahrnout //Prototypy funkcí. Názvy argumentů není třeba psát int odd(int); int sudý(int); void main() ( printf("pokud %d liché? %d\n", 11, liché(11)); printf("pokud %d liché? %d\n", 10, liché(10)); getch ( ) //Definice funkcí int sudá(int a) ( if (a) ( lichá(--a); ) else ( return 1; ) ) int lichá(int a) ( if (a) ( sudá(); - -a ) else ( návrat 0; ) )

Jedná se o smíšenou rekurzi – funkce lichá vrací 1, pokud je číslo liché, a 0, pokud je sudé.

Obvykle je deklarace funkce umístěna samostatně, v souboru .h, a definice funkcí v souboru .c. Hlavičkový soubor tedy představuje rozhraní knihovny a ukazuje, jak s ním pracovat, aniž byste se museli zabývat obsahem kódu.

Vytvoříme jednoduchou knihovnu. K tomu budete muset vytvořit dva soubory – jeden s příponou .h a umístit tam prototypy funkcí a druhý s příponou .c a umístit tam definice těchto funkcí. Pokud pracujete s IDE, musí být soubor .h vytvořen ve složce Header Files a soubory kódu ve složce Source Code Files. Nechť se soubory jmenují File1.ha File1.c
Přepišme předchozí kód. Takto bude vypadat hlavičkový soubor File1.h

#ifndef _FILE1_H_ #define _FILE1_H_ int odd(int); int sudý(int); #endif

Obsah souboru zdrojového kódu File1.c

#include "File1.h" int sudé(int a) ( if (a) ( liché(--a); ) else ( return 1; ) ) int liché(int a) ( if (a) ( sudé(-- a); ) else ( návrat 0; ) )

Naše hlavní funkce

#zahrnout #zahrnout #include "File1.h" void main() ( printf("if %d liché? %d\n", 11, liché(11)); printf("if %d liché? %d\n", 10, lichý(10));

Podívejme se na vlastnosti každého souboru. Náš soubor, který obsahuje hlavní funkci, obsahuje knihovny, které potřebuje, a také hlavičkový soubor File1.h. Kompilátor nyní zná prototypy funkcí, to znamená, že zná návratový typ, počet a typ argumentů a názvy funkcí.

Soubor záhlaví, jak bylo uvedeno výše, obsahuje prototyp funkce. Zde lze také zahrnout použité knihovny. Ochrana maker #define _FILE1_H_ atd. slouží k zabránění opětovnému kopírování kódu knihovny během kompilace. Tyto řádky lze nahradit jedním

#pragma Once int odd(int); int sudý(int);

Soubor zdrojového kódu File1.c obsahuje soubor záhlaví. Vše je logické a jednoduché jako obvykle. V hlavičkových souborech je kromě prototypů funkcí běžné zahrnout konstanty, substituce maker a definovat nové datové typy. Navíc právě v hlavičkových souborech můžete kód obsáhle komentovat a psát příklady jeho použití.

Předání pole jako argumentu

Jak již bylo zmíněno dříve, název pole je nahrazen ukazatelem, takže předání jednorozměrného pole je ekvivalentní předání ukazatele. Příklad: funkce přijme pole a jeho velikost a vypíše:

#zahrnout #zahrnout void printArray(int *arr, velikost bez znaménka) ( bez znaménka i; pro (i = 0; i< size; i++) { printf("%d ", arr[i]); } } void main() { int x = {1, 2, 3, 4, 5}; printArray(x, 10); getch(); }

V tomto příkladu může funkce vypadat takto

Void printArray(int arr, velikost bez znaménka) ( i bez znaménka; for (i = 0; i< size; i++) { printf("%d ", arr[i]); } }

Dovolte mi také připomenout, že pravidlo pro nahrazení pole ukazatelem není rekurzivní. To znamená, že při přenosu je nutné zadat rozměr dvourozměrného pole

#zahrnout #zahrnout void printArray(int arr, velikost bez znaménka) ( bez znaménka i, j; for (i = 0; i< size; i++) { for (j = 0; j < 5; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } void main() { int x = { { 1, 2, 3, 4, 5}, { 6, 7, 8, 9, 10}}; printArray(x, 2); getch(); }

Nebo můžete napsat

#zahrnout #zahrnout void printArray(int (*arr), velikost bez znaménka) ( bez znaménka i, j; for (i = 0; i< size; i++) { for (j = 0; j < 5; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } void main() { int x = { { 1, 2, 3, 4, 5}, { 6, 7, 8, 9, 10}}; printArray(x, 2); getch(); }

Pokud je dvourozměrné pole vytvořeno dynamicky, můžete předat ukazatel na ukazatel. Například funkce, která vezme pole slov a vrátí pole celých čísel rovných délce každého slova:

#zahrnout #zahrnout #zahrnout #zahrnout #define SIZE 10 unsigned* getLengths(const char **slova, velikost bez znaménka) ( unsigned *lengths = NULL; unsigned i; lengths = (unsigned*) malloc(size * sizeof(unsigned)); for (i = 0; i< size; i++) { lengths[i] = strlen(words[i]); } return lengths; } void main() { char **words = NULL; char buffer; unsigned i; unsigned *len = NULL; words = (char**) malloc(SIZE * sizeof(char*)); for (i = 0; i < SIZE; i++) { printf("%d. ", i); scanf("%127s", buffer); words[i] = (char*) malloc(128); strcpy(words[i], buffer); } len = getLengths(words, SIZE); for (i = 0; i < SIZE; i++) { printf("%d ", len[i]); free(words[i]); } free(words); free(len); getch(); }

Namísto vracení ukazatele na pole můžete předat pole, které je třeba vyplnit

#zahrnout #zahrnout #zahrnout #zahrnout #define SIZE 10 void getLengths(const char **slova, velikost bez znaménka, unsigned *out) ( unsigned i; for (i = 0; i< size; i++) { out[i] = strlen(words[i]); } } void main() { char **words = NULL; char buffer; unsigned i; unsigned *len = NULL; words = (char**) malloc(SIZE * sizeof(char*)); for (i = 0; i < SIZE; i++) { printf("%d. ", i); scanf("%127s", buffer); words[i] = (char*) malloc(128); strcpy(words[i], buffer); } len = (unsigned*) malloc(SIZE * sizeof(unsigned)); getLengths(words, SIZE, len); for (i = 0; i < SIZE; i++) { printf("%d ", len[i]); free(words[i]); } free(words); free(len); getch(); }

Zde první seznámení s funkcemi končí: téma je velmi rozsáhlé a je rozděleno do více článků.

V roce 1989 V rámci jazyka C++ byl void standardizován v roce 1998.

Následně klíčové slovo void a související jazykové konstrukce zdědily jazyky Java a C#, D.

Syntax

Syntakticky je void jedním ze specifikátorů typu zahrnutých do obecnější skupiny specifikátorů deklarací, ale v některých programovacích jazycích je implementován jako operátor. Například v JavaScriptu je void operátor a vždy vrací nedefinováno:

Neplatný výraz === nedefinováno ;

Sémantika

Sémantika klíčového slova void nepodléhá obecné sémantice specifikátorů typu a závisí na způsobu použití:

  • Jako název typu hodnoty vráceného funkcí: označuje, že funkce nevrací hodnotu a že volání takové funkce je výraz void. Tělo takové funkce by nemělo obsahovat příkazy return s výrazy. Například:

    Void f() ;

  • Jako součást deklarátoru funkce: označuje, že funkce má prototyp a žádné parametry. Například:

    Int f(void) ;

  • Jako název cílového typu operace přetypování: takové přetypování void znamená zřeknutí se hodnoty přetypovaného výrazu. Například:

    #define promotion_ptr() ((void) (ptr++))

  • Jako součást názvu typu prázdného ukazatele: takový ukazatel je schopen reprezentovat hodnoty libovolných ukazatelů na objekt a neúplné typy, tj. adresy libovolných objektů. Ukazatel prázdnoty je tedy zobecněným ukazatelem objektu. void ukazatele nejsou schopny reprezentovat hodnoty ukazatelů funkcí. Kromě případu přetypování konstantního nulového ukazatele na ukazatel funkce v C neexistují žádné explicitní ani implicitní převody mezi ukazateli void a ukazateli funkce.

Typ void je definován jako neúplný typ, který nelze rozšířit. V důsledku toho by se tento typ neměl používat tam, kde jsou povoleny pouze úplné typy, jako je typ parametru v definici funkce.

Jazyk C před zavedením void

Před zveřejněním prvního standardu C v roce 1989, který do jazyka zavedl klíčové slovo void, bylo běžnou praxí deklarovat funkce, které nevracely hodnotu, bez použití specifikátorů typu. Přestože tato deklarace byla sémanticky ekvivalentní deklaraci funkce vracející hodnotu typu int , záměrné vynechání specifikátorů typu zdůraznilo, že funkce nevrací žádnou konkrétní hodnotu. Například:

F(dlouhé l) ( /* ... */ )

Podobně definice funkcí, které neměly žádné parametry, byly zapsány s prázdnými závorkami:

Int main() ( /* ... */ )

Jako obecný ukazatel byl použit ukazatel na char. Moderní standardy navíc vyžadují, aby požadavky na reprezentaci a zarovnání pro ukazatele voidů byly stejné jako pro ukazatele char, což znamená, že typy jsou zaměnitelné.

První standardní dialekt C (C89), i když již umožňoval položky s klíčovým slovem void, stále umožňoval použití implicitního int, aby byla zachována kompatibilita s existujícím kódem. Moderní dialekt C (C99) neumožňuje absenci specifikátorů typu v názvech a deklaracích typů.

Příklady

Jsou uvedeny příklady deklarace funkce, která vrací void.

C++

Void message()

Jáva

Void message()

C#

Void message()

C

Void zpráva (neplatná)

Cíl-C

- (neplatná) zpráva;

D

Void message()

ActionScript

Zpráva funkce (): neplatná

Poznámky


Nadace Wikimedia. 2010.




Horní