• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Wskaźniki NULL w C i C++

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
0 głosów
142 wizyt
pytanie zadane 12 kwietnia w C i C++ przez whiteman808 Gaduła (4,760 p.)

Czytam https://stackoverflow.com/questions/1296843/what-is-the-difference-between-null-0-and-0 i nadal nie potrafię zrozumieć dlaczego poniższe fragmenty kodu są nieprawidłowe

// 1
int mojnull = 0;
int* wsk = funkcja_ktora_moze_zwrocic_wsk_null();
if (wsk == mojnull) {
    std::cerr << "Wystapil blad!\n";
    std::abort();
}
// 2 - na platformie gdzie wskaznik null jest reprezentowany przez 0xDEADBEEF
#define MYNULL 0xDEADBEEF
int* wsk = funkcja_ktora_moze_zwrocic_wsk_null();
if (wsk == MYNULL) {
    std::cerr << "Wystapil blad!\n";
    std::abort();
}

Wyjaśni mi ktoś łopatologicznie?

Przecież wskaźnik to zmienna przechowująca adres pamięci a w 1 adresem tym jest zero i mojnull też ma wartość zero, więc obie zmienne to obiekty przechowujące wartość zero tylko innego typu.

W 2 wskaźnik pusty jest reprezentowany przez 0xDEADBEEF na nietypowej platformie, za MYNULL po przetworzeniu przez preprocesor jest podstawiane 0xDEADBEEF i jest to porównywane z wartością zmiennej wsk a 0xDEADBEEF jest przecież wartością reprezentującą wskaźnik pusty na tejże platformie. Więc 0 to chyba powinien być konstrukt synktatyczny, który odpowiada 0xDEADBEEF.

3 odpowiedzi

+1 głos
odpowiedź 12 kwietnia przez adrian17 Mentor (354,120 p.)
edycja 13 kwietnia przez adrian17

(Schowałem drugie pytanie, bo to efektywnie to samo pytanie zadane innymi słowami. Nie spamuj proszę pytaniami, to zmniejsza szansę że na którekolwiek dostaniesz odpowiedź.)

1 ->

więc obie zmienne to obiekty przechowujące wartość zero tylko innego typu

A nie można porównywać zmiennych niekompatybilnych typów.

Bezpośrednie porównanie `wsk == 0` to jedyny wyjątek, bo literał 0 w kontekście w którym oczekiwany jest wskaźnik, jest traktowany (upraszczając) nie jako int, a jako null pointer tego typu. Więc jest to "porównanie wskaźnika ze wskaźnikiem" a nie "porównanie wskaźnika z intem", więc nie łamie reguły.

2 ->

Z tego co wiem* to nie ma znaczenia. Żeby porównać z null pointerem, nawet jeśli ma bitową reprezentację 0xDEADBEEF, wciąż użyjesz `== 0`, `== NULL` lub lepiej, `== nullptr`. Bo znowu - 0 tutaj nie oznacza że to binarna wartość 0, tylko że to null pointer.

* ponieważ platformy z niezerowym nullem to skrajny wyjątek i bardziej ciekawostka historyczna, więc mało kto się nad tym zastanawia.

komentarz 14 kwietnia przez tkz Nałogowiec (42,060 p.)

A nie można porównywać zmiennych niekompatybilnych typów.

To nie jest do końca prawda. Raczej nie możesz prównać czegoś, do czego nie stworzono oparatora porównania. Nawet jak mam klasę A i B, to jak stworzę operator, który będzie obsługiwał A==B lub B==A, to nadal typy są niekompatybilne, ale są możliwe do porównania. 

Bezpośrednie porównanie `wsk == 0` to jedyny wyjątek, bo literał 0 w kontekście w którym oczekiwany jest wskaźnik, jest traktowany (upraszczając) nie jako int, a jako null pointer tego typu. Więc jest to "porównanie wskaźnika ze wskaźnikiem" a nie "porównanie wskaźnika z intem", więc nie łamie reguły.

A tutaj raczej wchodzi niejawne rzutowanie typu. A traktowanie 0 jako cokolwiek znowu jest zależne od implementacji. Bo sam NULL może być i 0, i void*. 

ponieważ platformy z niezerowym nullem to skrajny wyjątek i bardziej ciekawostka historyczna, więc mało kto się nad tym zastanawia.

To nie kwestia platformy, a kompilatora. Pierwsze kompilatory do C faktycznie używały początek programu jako null.

komentarz 14 kwietnia przez adrian17 Mentor (354,120 p.)
edycja 14 kwietnia przez adrian17

Celowo tu językiem upraszczałem :)

Nawet jak mam klasę A i B, to jak stworzę operator, który będzie obsługiwał A==B lub B==A, to nadal typy są niekompatybilne, ale są możliwe do porównania. 

Nie miałem tutaj na myśli żadnego formalnego znaczenia słowa "kompatybilne", po prostu "kompatybilne na potrzebu porównania"; w takim znaczeniu dodanie operatora czyni je kompatybilnymi :)

A tutaj raczej wchodzi niejawne rzutowanie typu.

To nie jest niejawne rzutowanie, a przynajmniej nie tylko; jak sam widzisz w pytaniu, `wsk == mojnull` nie działa; nie działa nawet jeśli zmienna jest const(expr). Język konkretnie wymaga żeby to był literal / integer constant expression (zależnie od wersji standardu). W każdym razie najważniejsze co chciałem przekazać to że z punktu widzenia języka/kompilatora na poziomie typów to nie jest "porównanie wskaźnika z intem", bo ten literał 0 bardzo wcześnie jest traktowany jako reprezentujący wskaźnik a nie liczbę.

komentarz 15 kwietnia przez mokrowski Mędrzec (158,660 p.)

@adrian17, 

onieważ platformy z niezerowym nullem to skrajny wyjątek i bardziej ciekawostka historyczna, więc mało kto się nad tym zastanawia.

Dla C, to nie jest (aż taki) wyjątek. DSP mają często inną wartość niż 0 bo nie posiadają takiego fizycznego adresu i char ma tam często 16-bitów. W świecie embedded, pojawiają się nie tylko takie wyjątki.

0 głosów
odpowiedź 12 kwietnia przez WojAbuk Gaduła (3,280 p.)
Zacznijmy od tego że kod powinien działać niezależnie od platformy. Język C ma makro NULL które jest uniwersalne, a C++ ma słowo klocowe nullptr. Po prostu te rozwiązania są lepsze i niezależne od platformy. Jeszcze jest kwestia nie jawnej konwersji typów która w niektórych sytuacjach potrafi zrobić niespodziankę. Zdaje się że w normach ISO ((void*)0) działa zawsze, ale w ANSI C było to niezdefiniowane jak dobrze pamiętam i to mogło powodować problemy.
0 głosów
odpowiedź 15 kwietnia przez mokrowski Mędrzec (158,660 p.)
edycja 15 kwietnia przez mokrowski
Na stronie komisji WG14, ( https://www.open-std.org/jtc1/sc22/wg14/ ), znajduje się draft standardów C23 języka C ( https://www.open-std.org/jtc1/sc22/wg14/www/projects#9899 ). Dokładnie ten plik: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3467.pdf

Rozdział 7.21.3, strona 334.

W przypadku języków które posiadają standardy, warto je choćby "przeskanować wzrokiem" co w nich jest.

Podobne pytania

0 głosów
1 odpowiedź 524 wizyt
pytanie zadane 28 kwietnia 2018 w C i C++ przez BlinkyShay Obywatel (1,190 p.)
0 głosów
1 odpowiedź 376 wizyt
pytanie zadane 4 czerwca 2018 w C i C++ przez voik3 Nowicjusz (120 p.)
0 głosów
3 odpowiedzi 1,920 wizyt
pytanie zadane 9 maja 2017 w C i C++ przez seba Dyskutant (8,900 p.)

93,440 zapytań

142,432 odpowiedzi

322,679 komentarzy

62,802 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

...