Chyták pro C++ programátora

Petr B.

Re: Chyták pro C++ programátora
« Odpověď #15 kdy: 31. 10. 2010, 13:28:20 »
Především bych řekl, že adresa v paměti nemůže být nikdy 0
Zjevně offtopic k daném příkladu, ale kde si myslíš, že je po startu x86 uložená adresa handleru dělení nulou?  ;)

Řekl bych že někde jinde, než kde mohou být uloženy data.
A jen tak pro zajímavost, kde je specifikováno, že &NULL == 0? Resp. co znamená *NULL? Jestli to funguje, tak podle mne jen náhodou (né že bych byl odborník na C++, třeba se pletu :).


Anthony

Re: Chyták pro C++ programátora
« Odpověď #16 kdy: 31. 10. 2010, 13:28:39 »
Nešlo by to přeložit do pascalu nebo assembleru x86 pro ty co neumí C+-x:

D.A. Tiger

  • ****
  • 486
  • Tygr, který žere tučňáka ;-)
    • Zobrazit profil
    • E-mail
Re: Chyták pro C++ programátora
« Odpověď #17 kdy: 31. 10. 2010, 13:42:15 »

A jen tak pro zajímavost, kde je specifikováno, že &NULL == 0? Resp. co znamená *NULL? Jestli to funguje, tak podle mne jen náhodou (né že bych byl odborník na C++, třeba se pletu :).

NULL je v C++  :
Kód: [Vybrat]
#define NULL 0

Logik

  • *****
  • 1 022
    • Zobrazit profil
    • E-mail
Re: Chyták pro C++ programátora
« Odpověď #18 kdy: 31. 10. 2010, 13:43:27 »
Možná kecam, ale z hlavy bych řek, že NULL je definovaný jako

#DEFINE NULL 0

Z čehož vyplývá, že věci typu *NULL nebo &NULL je nesmysl.

Tak jsem se kouk. V souboru sys/_null.h (includovaný ze stdio.h) je definice:
Kód: [Vybrat]
#ifndef NULL

#if defined(_KERNEL) || !defined(__cplusplus)
#define NULL    ((void *)0)
#else
#if defined(__LP64__)
#define NULL    (0L)
#else
#define NULL    0
#endif  /* __LP64__ */
#endif  /* _KERNEL || !__cplusplus */

#endif
Takže jsem se skoro trefil. Až na to, že *NULL vlastně smysl alespoň teoreticky má - něco na adrese 0 bude. Používat to bych ale nedoporučoval...
EDIT: tak oprava, v C++ to opravdu smysl nemá, tam 0 není přetypovaná na void.

D.A. Tiger: V hlavičkových souborech je zcela určitě, jde o to, jestli je v normě...
« Poslední změna: 31. 10. 2010, 14:22:58 od Matyáš Novák »

Petr B.

Re: Chyták pro C++ programátora
« Odpověď #19 kdy: 31. 10. 2010, 13:57:24 »
Citace
NULL je v C++  :
Kód: [Vybrat]
#define NULL 0

NULL je ukazatel, takže je to
Kód: [Vybrat]
#define nULL (void *) NULL
*NULL označuje tedy hodnotu na adrese 0, tedy nějaké číslo (může a nemusí to být nula, to je asi fuk).
Když si definuji Typ *p = NULL, potom &p == *nejaka adresa v pameti, zarucene nenulova*

Co ale udělá &NULL, ke kterému dojde v příkladu (jestli se nepletu)? Kde je to definováno?


Petr B.

Re: Chyták pro C++ programátora
« Odpověď #20 kdy: 31. 10. 2010, 13:58:22 »
Samozřejmě je to #define NULL    ((void *)0)  :o

XYCZ

Re: Chyták pro C++ programátora
« Odpověď #21 kdy: 31. 10. 2010, 14:05:18 »
Především bych řekl, že adresa v paměti nemůže být nikdy 0
Zjevně offtopic k daném příkladu, ale kde si myslíš, že je po startu x86 uložená adresa handleru dělení nulou?  ;)

Řekl bych že někde jinde, než kde mohou být uloženy data.
A jen tak pro zajímavost, kde je specifikováno, že &NULL == 0? Resp. co znamená *NULL? Jestli to funguje, tak podle mne jen náhodou (né že bych byl odborník na C++, třeba se pletu :).
Zmíněná adresa handleru je uložená právě na adrese nula (dokud se nezmění IDTR). x86ce brání ve vykonávání kódu od prvního bytu chybějící příznak Execute, popř. příliš vysoká hodnota CPL.

M$:
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif

D.A. Tiger

  • ****
  • 486
  • Tygr, který žere tučňáka ;-)
    • Zobrazit profil
    • E-mail
Re: Chyták pro C++ programátora
« Odpověď #22 kdy: 31. 10. 2010, 14:10:59 »
Samozřejmě je to #define NULL    ((void *)0)  :o

Ano ale v C. V C++ se tato konstrukce jako NULL pouzivat nesmi.

D.A. Tiger

  • ****
  • 486
  • Tygr, který žere tučňáka ;-)
    • Zobrazit profil
    • E-mail
Re: Chyták pro C++ programátora
« Odpověď #23 kdy: 31. 10. 2010, 14:20:13 »
Možná kecam, ale z hlavy bych řek, že NULL je definovaný jako

#DEFINE NULL 0

Z čehož vyplývá, že věci typu *NULL nebo &NULL je nesmysl...

Ano, je videt, ze si rozumime :-)

Citace
D.A. Tiger: V hlavičkových souborech je zcela určitě, jde o to, jestli je v normě...

Hlavu za to nedam, ale rekl bych ze norma minimalne zakazuje starou C definici...
« Poslední změna: 31. 10. 2010, 14:22:08 od D.A. Tiger »

Logik

  • *****
  • 1 022
    • Zobrazit profil
    • E-mail
Re: Chyták pro C++ programátora
« Odpověď #24 kdy: 31. 10. 2010, 14:33:10 »
Tak máš pravdu, C++ standard definuje NULL, a to jako typ integer 0.
Citace
18.1.3
The macro NULL is an implementation-defined C++ null pointer constant in this International Standard (4.10). *188)
188) Possible definitions include 0 and 0L, but not (void*)0.

4.10.1
A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to zero. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of pointer to object or pointer to function type. Two null pointer values of the same type shall compare equal. The conversion of a null pointer constant to a pointer to cv-qualified type is a single conversion, and not the sequence of a pointer conversion followed by a qualification conversion (4.4).

ondra.novacisko.cz

Re: Chyták pro C++ programátora
« Odpověď #25 kdy: 31. 10. 2010, 15:06:11 »
Referencovat NULL nejde, ale jde dereferencovat pointer s hodnotou NULL. Pokud udělám
Kód: [Vybrat]
int *a = 0;
int b = *a;

tak mě to spadne na SIGSEG

Pokud ale napíšu

Kód: [Vybrat]
int *a = 0;
int &b = *a;

Pak program nespatne, ale vytvořím referenci na proměnnou int na adrese 0. On rozdíl mezi referencí a pointer není žádný, jde jen o syntaxtický zápis. Ale má určitý význam, a o tom to je.

Jinak NULL v C++ opravdu není, přesto jej radši používám, protože se to líp čte. Ještě raději používám
Kód: [Vybrat]
enum NilType {
   nil = 0
}

A přiřazuji nil. Tohle je zajímavý u chytrých ukazatelů, které by jinak bylo nutné konstrukovat s parametrem int pro vytvoření neininicalizovaného chytrého ukazatele. Napsat konstruktor reagující na NilType je rozhodně lepší.

Zajímavý je, že s NULL i s nulou má C++ obecně docela problémy, například při instanciování šablon funkcí. Proto se myslím C++0x plánuje typovaný NULL. Čili zpět od obecné nuly k nějakému speciálnímu typu.

Logik

  • *****
  • 1 022
    • Zobrazit profil
    • E-mail
Re: Chyták pro C++ programátora
« Odpověď #26 kdy: 31. 10. 2010, 15:30:53 »
Citace
Referencovat NULL nejde, ale jde dereferencovat pointer s hodnotou NULL.
Což není divu, když pointer s hodnotou NULL má právě jinej typ než NULL samotný.
Což je IMHO právě záměr standardu - aby se alespoň částečně zamezilo nechtěnému dereferencování NULL.

Řešení s enum pro šablony je ale hezkej příklad C++ kouzelnictví.

D.A. Tiger

  • ****
  • 486
  • Tygr, který žere tučňáka ;-)
    • Zobrazit profil
    • E-mail
Re: Chyták pro C++ programátora
« Odpověď #27 kdy: 31. 10. 2010, 15:47:37 »
Zajímavý je, že s NULL i s nulou má C++ obecně docela problémy, například při instanciování šablon funkcí. Proto se myslím C++0x plánuje typovaný NULL. Čili zpět od obecné nuly k nějakému speciálnímu typu.

No treba knihovna Loki, definujici sablony pro genericke programovani (hlavne) knihoven, ktere zachazeji s typy ( trida, struktura) jako s objekty samotnymi, uz pomerne dlouho takovy jednoduchy typ pouziva. Neco ve stylu

Kód: [Vybrat]
struct nil_type { };
 

Vyuziva to treba v typovych seznamech, atpd.... Ale netusim, jak by se to dalo pouzit tak jako Makro NULL. To neni ukazatel, ale prece jen cislo adresy, ktere slouzi pouze k testovacim ucelum, zadna pouzitelna data na ni nikdy nebudou...

JS

Re: Chyták pro C++ programátora
« Odpověď #28 kdy: 31. 10. 2010, 18:08:57 »
Tak uz jsem tu ztrapnil, ale nemohl se ten programator pokusit predat nulovy pointer z te funkce, ktera je definovana ze vraci odkaz, ktery, pokud se nepletu, narozdil od pointeru, nikdy NULL byt nemuze?

Nerikam, ze to schvaluji. Ale neni mozne, ze tim potreboval obejit nejaky problem - treba omezeni dane nejakym rozhranim?

ondra.novacisko.cz

Re: Chyták pro C++ programátora
« Odpověď #29 kdy: 31. 10. 2010, 18:20:10 »
Nerikam, ze to schvaluji. Ale neni mozne, ze tim potreboval obejit nejaky problem - treba omezeni dane nejakym rozhranim?

To je samozřejmě možné, ale už z principu u rozhraní nevíme, kdo je na druhé straně. A pokud ten na druhé straně vidí referenci, může být dost překvapen, když ta reference je nulová. V tom rozhraní to určitě má smysl. A pokud nám to z nějakého důvodu nevyhovuje, můžeme
  • použít jiné rozhraní
  • vrátit referenci na proměnnou se speciální hodnotou (která pro mě znamená chybu)
  • vrátit referenci na proměnnou s bezpečnou hodnotou a objekt nastavit do chybového stavu (zjistitelný přes jiné rozhraní)
  • vyhodit výjimku - což je běžný postup, třeba dynamic_cast na referenci taky vyhazuje výjimku, pokud se převod nezdaří. nemůže vrátit nulovou referenci

PS: Jiným rozhraním se myslí extra rozhraní, který konkrétní implementace navíc dědí a do kterého se dostaneme dynamic castováním původního rozhraní na nové rozhraní.