Diskuze: Ukazatele jazyk C
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.
Člen
Zobrazeno 16 zpráv z 16.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.
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á).
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
Výjimku by to nezpůsobilo, o tom si v C/C++ můžeš nechat jenom zdát ...nejspíš by to prostě spadlo
Ano, jak řiká Lukáš tak to spadlo..
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!
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ů.
V C++ výjimky jsou, ale chybný přístup do paměti ani použití neinicializované proměnné výjimku nehází.
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.
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).
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.
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á.
Záleží na nastavení, i Access violation se dá odchytit, pokud použiješ
přepínač /EHa
http://msdn.microsoft.com/…deeycx5.aspx
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.
To jsem nevěděl, ale ve Visual studiu jsem v C++ zase tak moc nedělal
Zobrazeno 16 zpráv z 16.