Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Ukazatele jazyk C

Aktivity
Avatar
pokusnicek
Člen
Avatar
pokusnicek:19.5.2014 16:19

Ahoj,

mám zde takový problém, potřeboval bych zde na kodu vysvětlit pár věcí.

#include<stdio.h>
#include<stdlib.h>

int main(){
int a;int b;int *p_a; int *p_b;
scanf("%i",&a);
scanf("%i",&b);
p_a = &a;
p_b = &b;
printf("Vysledek je:%i",*p_a+*p_b);



}

Zadeklaroval jsem si ukazatele int *p_a; Proč tedy adresou &a plním -> p_a bez hvezdicky?

Díky

Editováno 19.5.2014 16:20
 
Odpovědět
19.5.2014 16:19
Avatar
Luboš Běhounek Satik:19.5.2014 16:57

Protože &a je reference na a, tedy její adresa v paměti.

S hvězdičkou by jsi na místo, kam p_a ukazuje, uložil obsah &a, tedy její adresu (ovšem tenhle kus kódu by způsobil výjimku, protože by p_a ještě nebyla inicializovaná).

Nahoru Odpovědět
19.5.2014 16:57
https://www.facebook.com/peasantsandcastles/
Avatar
Odpovídá na pokusnicek
Neaktivní uživatel:19.5.2014 17:04

Já jen doplnim takovy priklad, jak by to mohlo vypadat

Na začátku máš:

Adresa  1000    1001    1002    1003
Jméno  a       b       p_a     p_b
Hodnota ???     ???     ???     ???

Po scanf

hodnota a = 23
hodnota b = 42

Po přiřazení

p_a = &a;
hodnota p_a = 1000
p_b = &b;
hodnota p_b = 1001

Takže

&a      1000
a       23
*(&a)   23
*a      netuším, asi chyba

&p_a    1002
p_a     1000
*(&p_a) 1000
*p_a    23
Editováno 19.5.2014 17:05
Nahoru Odpovědět
19.5.2014 17:04
Neaktivní uživatelský účet
Avatar
Lukáš Hruda
Tvůrce
Avatar
Odpovídá na Luboš Běhounek Satik
Lukáš Hruda:19.5.2014 19:46

Výjimku by to nezpůsobilo, o tom si v C/C++ můžeš nechat jenom zdát :D ...nejspíš by to prostě spadlo

 
Nahoru Odpovědět
19.5.2014 19:46
Avatar
pokusnicek
Člen
Avatar
pokusnicek:19.5.2014 19:51

Ano, jak řiká Lukáš tak to spadlo..

 
Nahoru Odpovědět
19.5.2014 19:51
Avatar
LukyH
Člen
Avatar
Odpovídá na Lukáš Hruda
LukyH:25.5.2014 18:49

V C výjimky nejsou, ačkoliv něco by tu bylo: http://en.wikibooks.org/…ror_handling. V C++ už však jsou: http://www.cplusplus.com/…/exceptions/. Takže, probuďte se ze snu!

 
Nahoru Odpovědět
25.5.2014 18:49
Avatar
LukyH
Člen
Avatar
LukyH:25.5.2014 19:49

Tak do třetice, prosím poslední dva příspěvky mi smažte.

Zápis

int *p_a;

znamená že chceš vyhradit kus paměti pro uložení adresy jenž bude ukazovat na jiné paměťové místo kde se nachází <b>int</b> a tuto pamět si pojmenuješ jako <b>p_a</b> (Tedy nikoliv pointer <b>*p_a</b>). Někteří programátoři proto píší

int* p_a;

jakože <b>int*</b> je datový typ "pointer na int". Použitím hvězdičky mimo deklaraci pak určuješ způsob práce s takovou proměnnou <b>p_a</b>. Bez hvězdičky, tj. bez dereferencování přistupuješ k obsahu takové proměnné jako k adrese "někam". Pokud použiješ hvězdičku tak dereferencováním získaš přístup k hodnotě, která se nachází na adrese uložené v <b>p_a</b>.

Např.

int a = 10;
int* p_i = &a; /* Do p_i uložíme adresu proměnné a */

printf("Obsah propměnné a: %d\n",a);
*p_i = 20; / Na adresu kam ukazuje proměnná p_a, tj. na uložiště proměnné a uložíme novou hodnotu */
printf("Obsah propměnné a podruhe: %d",a);

Výpis by měl být:
Obsah propměnné a: 10
Obsah propměnné a: 20

Mimichodem velikost proměnné p_a bude stejná jako např. pointeru na datový typ float, double nebo char - je to pouze adresa která na 32-bitových systémech většinou má velikost 32 bitů a na 64 bitových systémech má 64-bitů.

 
Nahoru Odpovědět
25.5.2014 19:49
Avatar
Lukáš Hruda
Tvůrce
Avatar
Odpovídá na LukyH
Lukáš Hruda:25.5.2014 22:36

V C++ výjimky jsou, ale chybný přístup do paměti ani použití neinicializované proměnné výjimku nehází.

 
Nahoru Odpovědět
25.5.2014 22:36
Avatar
LukyH
Člen
Avatar
LukyH:25.5.2014 22:47

Ano máte zřejmě pravdu, Vaše tvrzení jsem spíš chápal v šiším kontextu. Moje chyba.

 
Nahoru Odpovědět
25.5.2014 22:47
Avatar
Odpovídá na LukyH
Patrik Valkovič:25.5.2014 23:22

Jen doplním že první příklad, tedy "int *p_a;" nevyhradí žádný kus paměti. Pouze vytvoří ukazatel, který ukazuje "někam" (podle uložených bitů). Pro vytvoření místa pro proměnnou se musí zavolat "new" (halda) nebo vytvořit explicitně (jak je uvedeno v příkladu, poté se jedná pouze o lokální proměnnou).
Co se výjimek v C++ týče, myslím že jen velmi málo standartních metod vyvolá výjimku (jestli vůbec některé, hlavně kvuli výkonu), takže vyvolání výjimky závisí na programátorovi.

Nahoru Odpovědět
25.5.2014 23:22
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Odpovídá na Lukáš Hruda
Luboš Běhounek Satik:25.5.2014 23:28

Ono záleží na situaci, zrovna tady (v C++)

int a=10;
int *p_a;
*p_a = (int)&a;

to (s nějvětší pravděpodobností) spadne s výjimkou Access violation, ale pokud by jeho program byl složitější, pak se zvyšuje šance, že si místo Access violation přepíše nějaké místo, kde má nějaká jiná data.

BTW od VS2012 je defaultně nastavené, že neinicializované proměnné ti to hlásí při kompilaci jako error, takže to ani nezkompiluješ :) (přepínač SDL checks).

Nahoru Odpovědět
25.5.2014 23:28
https://www.facebook.com/peasantsandcastles/
Avatar
LukyH
Člen
Avatar
Odpovídá na Patrik Valkovič
LukyH:26.5.2014 1:40

Můžete mi vysvětlit co technicky obnáší takové "vytvoření" proměnné, jak na zásobníku tak na haldě? Není to přeci jenom jistý způsob rezervace/vyhrazení paměti počítače? Myslím že neznalí čtenář může teď nabývat dojmu, že taková proměnná nespotřebuje žádnou paměť. Jako kdybychom nyní hovořili o imaginárních věcech. Ti znalejší jistě pochopí jak jsem výklad myslel. Nakonec si nemyslím že bych uvedl něco na nesprávnou míru. Přesto ale byl bych rád kyby mě i ostatní přiučili v chápání uvedeného výkladu.

 
Nahoru Odpovědět
26.5.2014 1:40
Avatar
Lukáš Hruda
Tvůrce
Avatar
Odpovídá na Luboš Běhounek Satik
Lukáš Hruda:26.5.2014 11:18

Nejsem si jistý, ale access violation podle mě není výjimka ale pouze chybová hlaška kterou generuje operační systém při pádu programu způsobeném přístupem do paměti, do které se přistupovat nemá, odchytit se podle mě nedá.

 
Nahoru Odpovědět
26.5.2014 11:18
Avatar
Odpovídá na Lukáš Hruda
Luboš Běhounek Satik:26.5.2014 12:41

Záleží na nastavení, i Access violation se dá odchytit, pokud použiješ přepínač /EHa
http://msdn.microsoft.com/…deeycx5.aspx

Nahoru Odpovědět
26.5.2014 12:41
https://www.facebook.com/peasantsandcastles/
Avatar
coells
Tvůrce
Avatar
Odpovídá na Lukáš Hruda
coells:26.5.2014 12:43

Kupodivu se odchytit dá :-)

Pokud mluvíme o Windows a Microsoft Visual C++, je podporovaný mechanismus Structured Exception Handling, který lze povolit na kompilátoru. V případě access violation se jedná o hardwarovou výjimku, kterou lze odchytit tradičním mechanismem C++ výjimek.

V případě UNIXových systémů je situace trochu jiná. Zde dojde k vyvolání signálu SIGSEGV, který lze odchytit uživatelským signal handlerem. Je možné, že některé kompilátory podporují i variantu s výjimkou, ale to už záleží na vendorovi.

 
Nahoru Odpovědět
26.5.2014 12:43
Avatar
Lukáš Hruda
Tvůrce
Avatar
Odpovídá na coells
Lukáš Hruda:26.5.2014 21:59

To jsem nevěděl, ale ve Visual studiu jsem v C++ zase tak moc nedělal :)

 
Nahoru Odpovědět
26.5.2014 21:59
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 16 zpráv z 16.