Avatar
Kejmou
Člen
Avatar
Kejmou:

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):

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
:)
Avatar
Posix
Člen
Avatar
Odpovídá na Kejmou
Posix:

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  +1 19.5.2014 17:04
Proč to dělat jednoduše, když to jde složitě.
Avatar
Odpovídá na Luboš Běhounek (Satik)
Lukáš Hruda (Luckin):

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
Kejmou
Člen
Avatar
Kejmou:

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 (Luckin)
LukyH:

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:

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í int a tuto pamět si pojmenuješ jako p_a (Tedy nikoliv pointer *p_a). Někteří programátoři proto píší

int* p_a;

jakože int* 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 p_a. 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 p_a.

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
Odpovídá na LukyH
Lukáš Hruda (Luckin):

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:

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
patrik.valkovic
Šéfredaktor
Avatar
Odpovídá na LukyH
patrik.valkovic:

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 (Luckin)
Luboš Běhounek (Satik):

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
:)
Avatar
LukyH
Člen
Avatar
Odpovídá na patrik.valkovic
LukyH:

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
Odpovídá na Luboš Běhounek (Satik)
Lukáš Hruda (Luckin):

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 (Luckin)
Luboš Běhounek (Satik):

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
:)
Avatar
coells
Redaktor
Avatar
Odpovídá na Lukáš Hruda (Luckin)
coells:

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
Odpovídá na coells
Lukáš Hruda (Luckin):

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.