Veľkonočná akcia je tu a s ňou aj extra kredity ZADARMO na náš interaktívny e-learning. Dobij si teraz kredity a posuň sa vo svojej kariére vpred!
Zarábaj až 6 000 € mesačne! Akreditované rekvalifikačné kurzy od 0 €. Viac informácií.

Diskusia – 7. diel - Polia v jazyku C

Späť

Upozorňujeme, že diskusie pod našimi online kurzami sú nemoderované a primárne slúžia na získavanie spätnej väzby pre budúce vylepšenie kurzov. Pre študentov našich rekvalifikačných kurzov ponúkame možnosť priameho kontaktu s lektormi a študijným referentom pre osobné konzultácie a podporu v rámci ich štúdia. Toto je exkluzívna služba, ktorá zaisťuje kvalitnú a cielenú pomoc v prípade akýchkoľvek otázok alebo projektov.

Komentáre
Avatar
DarkCoder
Člen
Avatar
Odpovedá na Patrik Pastor
DarkCoder:23.8.2019 21:33

Přetypování ukazatele se nejčastěji používá ve funkcích které přebírají obecný ukazatel, čímž je lze použít pro více typů dat. Funkce porovnej je typický příklad. Dále například různé třídící algoritmy jako quicksort(), alokovaní paměti pomocí malloc(), apod.

Obecný ukazatel je má v definici klíčové slovo void.

void *p = NULL; // obecny ukazatel

Obecný ukazatel je typ ukazatele, který může ukazovat na libovolný typ dat. Avšak předtím, než je použit pro získání hodnoty pomocí dereference ukazatele, musí být přetypován na správný typ dat.

Podívejme se na následující příklad.

#include <stdio.h>

int main(void) {
        char c = 'x';
        int i = 10;
        float f = 100.0f;
        void *p = NULL; // obecny ukazatel

        p = &c; // ukazuje na char
        printf("%c\n", *(char*)p);

        p = &i; // ukazuje na int
        printf("%d\n", *(int*)p);

        p = &f; // ukazuje na float
        printf("%f\n", *(float*)p);

        return 0;
}

V příkladu jsou definovány a inicializovány tři proměnné a jeden obecný ukazatel. Jeho datový typ je void. Hodnota NULL říká, že na nic neukazuje. Je dobré NULL používat pokud ukazatel neukazuje na nic. Postupně tomuto ukazateli přiřazujeme adresy na různé typy dat. Abychom s těmito typy dat mohli pracovat, např. je vypsat, musíme obecný ukazatel před použitím na tento typ přetypovat.

p = &c; // ukazuje na char
printf("%c\n", *(char*)p);

Hvězdička uvnitř závorek říká, že přetypováváme na znakový ukazatel. Opominutí hvězdičky by byla chyba. p je totiž ukazatelová proměnná, nikoli běžná proměnná. Hvězdička před závorkami říká, že se bere hodnota uložena na adrese ukazatele, toto je dereferencování ukazatele.

Ikdyž funkce porovnej() může vracet mnoho hodnot, v závislosti na hodnotách obou operandů, bere se z ní pouze stavy o rovnosti. Nyní by Ti mělo být jasné jak funkce porovnej() funguje.

Odpovedať
23.8.2019 21:33
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovedá na DarkCoder
Patrik Pastor:23.8.2019 21:44

jo diky toto je mnohem jasnejsi. Ovsem stale nerozumim ani z toho co jsem cetl na netu jak vlasne VNITRNE probiha dereference. chapu, ze kdyz treba "int a = *p" tedy ze hvezdicka dereferencuje pointer "p" na jeho hodnotu. Ovsem to je pouze zapis. Jak je to s pointerem v pameti?
podle toho jak to chapu by mel vyt pointer ulozen na 3 mistech:

  1. vlastni adresa pointera
  2. adresa hodnoty na kterou pointer ukazuje (napr &a)
  3. hodnota adresy na kterou pointer ukazuje (*p)

ale pointer prece ma jenom adresu promenne, JAK se tedy dostane k HODNOTE teto promenne? dereferencuje? co to vnitrne zname? kde je tato hodnota ulozena a jak se k ni te pointer dostame potom?

dik za odpoved. Jsem v tomto novy, ale toto mi opravdu vrta hlavou

 
Odpovedať
23.8.2019 21:44
Avatar
Odpovedá na Patrik Valkovič
Patrik Pastor:23.8.2019 22:12

fakt nevim ani wiki mi nepopsala co se UVNITR - v pameti deje (nikoliv syntax) dereference. viz otazka vyse. Mam proble pochopit jak pointer dostane Hodnotu z promenne (kdyz si drzi POUZE jeji adresu, ale ne uz jeji hodnotu prave). -viz otazka vyse

 
Odpovedať
23.8.2019 22:12
Avatar
DarkCoder
Člen
Avatar
Odpovedá na Patrik Pastor
DarkCoder:23.8.2019 22:14

Jednoduše. Pointer je proměnná, která v sobě uchovává adresu jiného objektu. Je třeba naučit se číst definice a výrazy.

int i = 10;
int *p = &i; // inicializace ukazatele (hvězdička nutná, jedná se o ukazatel)

p = &i; // do p je přiřazena adresa i (hvězdička být nesmí)

printf("%d\n", *p); // výpis i pomocí ukazatele

chapu, ze kdyz treba "int a = *p" tedy ze hvezdicka dereferencuje pointer "p" na jeho hodnotu

Ne. Dereferenci ukazatele *p musíš číst takto: Hodnota ukazatele uložena na adrese v p.
Hodnota uložena v pointeru je adresa objektu, na který tento ukazatel ukazuje. Což je něco jiného než hodnota na adrese uložené v pointeru.

Pointer je pořád proměnná a stejně jako jiná proměnná má svoji adresu a je uložen pouze na jednom místě. Adresu pointeru využíváš u double pointeru, nikoli u "klasického" pointeru na typ. Vše je záležitostí překladače. Ten díky tomu, že zná adresu objektu (proměnné, funkce, objektu), může přímo získávat hodnotu uložené na dané adrese. Je třeba si uvědomit dvě věci. Čtením hodnoty na adrese nic nezkazíš, maximálně získáš nesmyslnou hodnotu pokud to napíšeš špatně. Pokud se ale pokusíš zapsat něco na adresu která není tvoje, může dojít k havárii systému.

Odpovedať
23.8.2019 22:14
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovedá na DarkCoder
Patrik Pastor:23.8.2019 22:32

to jsi mi ale stale nedal zadnou odpoved. Rekl jsi mi syntax, ale na to jsem se.prave Neptal (jeste jsem to zduraznoval). Me zajima JAK VNITRNE pointer, ktery ma ulozenou adresu promenne, se dostane k hodnote teto adresy (protoze pointer si drzi JENOM adresu, ale nedrzi si uz hodnotu na teto adrese) - to je na co se ptam, jak probiha -jeste jednou VNITRNE, v pameti - dereference. To znamena jak se pointer ktery si drzi adresu promenne, dostane na hodnotu teto adresy (kterou uz si ale NEdrzi).

 
Odpovedať
23.8.2019 22:32
Avatar
DarkCoder
Člen
Avatar
Odpovedá na Patrik Pastor
DarkCoder:23.8.2019 22:42

Je to uvedené v posledním odstavci mého příspěvku. Pointer se nedostává k hodnotě uložené na adrese, kterou uchovává. K tomu se dostává operační systém. Překladač přeloží program do počítačem srozumitelného a čitelného tvaru, po spuštění programu jsou instrukce čteny operačním systémem a ten si přistupuje k daným datům. Když zná adresu, může se na tuto adresu podívat a hodnotu přečíst a vrátit.

Odpovedať
23.8.2019 22:42
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovedá na DarkCoder
Patrik Pastor:23.8.2019 22:47

takze pointer sice ulehcuje misto, tim, ze se pouze odkazuje, ale na ukor prekladace - ktery musi jeste prelozit z adresy hodnotu. Tak jaka je potom vyhoda pointeru, kdyz prekladac stejne udala to co bych udelal.ja bez pointeru - zkopiroval promennou, misto abych se na ni referencoval. vysledne mnozstvi strojovych instrukci je stejne - bud to skopiruju (je to narocne) - ale jinak to udal prekladac - takze to vyjde na stejno

 
Odpovedať
23.8.2019 22:47
Avatar
Odpovedá na Patrik Pastor
Patrik Valkovič:23.8.2019 22:52

Tvlj příspěvek na StackOverflow byl míněný dobře, jen vůbec nedává smysl.
Ukazatel je ve skutečnosti pouze adresa - číslo. Tj. teoreticky můžeš napsat int* x = 0x4F3C4F18 (ta koncovka u nedává smysl). Poté, když dereferencuješ takový ukazatel, říkáš tím "dej mi hodnotu na adrese 0x4F3C4F18". Takhle si to lze představit zjednodušeně.
Problém 1 - velikost ukazatele se může lišit mezi platformama, někde může mít 32 bitů, někde 64 a někde jen 24. Nemůžeš tedy do proměnné uložit adresu, to nedává smysl.
Problém 2 - operační systém si paměť hlídá a když mu sáhneš někam, kam to nemáš povoleno, tak program násilně ukončí (viz Terminated). Dnešní operační systémy aplikují tzv. stránkování (memory paging), takže pokud chceš vědět, jak to funguje pod kapotou, nastuduj si tohle.

Odpovedať
23.8.2019 22:52
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Odpovedá na Patrik Valkovič
Patrik Pastor:23.8.2019 22:56

jop diky. Docela zajimave tema uz sem se na to dival na wiki - memory paging , ale je to jeste celkem hard.
me byc treba zajimalo, ale jestli je mozne i toto zmenit - jak si OS managuje pamet. V cem jsou instrukce napsany a jestli i toto je mozne naprogramovat. Je to napsane v asm? nebo uz rovnou v binarce?... jsem na ubuntu =, tak by snad byla moznost jak se podivat i do techto systemovych souboru se zdrojaky :D

 
Odpovedať
23.8.2019 22:56
Avatar
Odpovedá na Patrik Pastor
Patrik Valkovič:23.8.2019 23:05

Ne, způsob práce s paměti z hlediska operačního systému nezměníš. Ono je to koneckonců pro programátora skryté.
Jinak se zdá, že je to psáno v C - https://github.com/…/mm/memory.c

Odpovedať
23.8.2019 23:05
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zobrazené 10 správy z 40.