2010-02-24 11 views
7

Chcę przedefiniować NULL w moim programie, takie jakJak zdefiniować za pomocą #define NULL

#define MYNULL ((void*)0) 

Ale definicja ta nie działa w następującym stwierdzeniem:

char *ch = MYNULL; 

Error : nie można przekonwertować z pustki * na char *

Jaki byłby najlepszy sposób zdefiniowania wartości NULL?

+12

Jaki język? C lub C++, to są bardzo różne języki. –

+14

A dlaczego uważasz, że musisz to zrobić? –

+0

Czy możesz zmienić nazwę zmiennej ch na coś innego (jak 'str'), ponieważ może to wprowadzić w błąd kogoś, kto czyta ją szybko, kto może ci powiedzieć, że jesteś zainteresowany obsługą NUL. (Ale moim prawdziwym pytaniem jest (jak zapytał @Neil Butterworth), DLACZEGO?) (Czy możesz wyjaśnić, co masz nadzieję osiągnąć? Czy starasz się, aby pojedynczy manifest miał stałą podwójną powinność jako zarówno wskaźnik, jak i postać NUL ? –

Odpowiedz

16
#ifdef __cplusplus 
#define MYNULL 0 
#else 
#define MYNULL ((void*)0) 
#endif 

będzie działać w obu z nich.

+3

-1 To jest zły pomysł, jak omówiono w innych odpowiedziach –

+0

@Ruben: Zgadzam się, jednak jeśli piszesz agnostyczną bibliotekę językową (tj. Chcesz, aby kod kompilował się w obu językach), potrzebujesz jakiegoś sposobu to. Mówi się z zastrzeżeniem, że są to różne języki, a "agnostyczna biblioteka języków" dla C & C++ to hack. –

+0

@Binary Worrier: Jeśli budujesz podstawową wymianę całej Biblioteki standardowej dla nowego kompilatora, który właśnie opracowałeś, aby zrobić landgrab dla udziału w szybko rozwijającym się rynku kompilatorów C/C++, to świetny pomysł. Jeśli nie jesteś na tym stanowisku, nie widzę, jak to się poprawi na tym, co jest wbudowane * i * nie ma żadnych złych efektów ubocznych, takich jak brak dobrej gry z 'nullptr', jak zauważono w odpowiedzi @ Johannesa lub wszelkie inne przyszłe rzeczy, z którymi może wchodzić w interakcję. –

2
#define MYNULL 0 

będzie działać w C++

+2

To będzie działać tylko dla C++. C musi NULL być #defined jako (void *) 0. –

+0

Dzięki! To zadziałało! – cppdev

+0

Jaki jest najlepszy sposób, aby działał zarówno w c, jak i C++ – cppdev

28
#define MYNULL NULL 

jest najbezpieczniejszym, nie widzę powodu, w ten sposób, ale jeśli naprawdę chcesz, idź do przodu. Oto jak C i C++ zrobić to odpowiednio:

#define NULL 0 //C++ 
#define NULL ((void*)0) //C 

Generalnie definiując 0 dla NULL jest zły nawyk, to faktycznie ma to być częścią języka. C++ 0x adresuje to.

To co Bjarne Stroustrup musi say on this:

powinienem używać NULL lub 0?

W języku C++ definicja wartości NULL to 0, , dlatego różnica jest tylko estetyczna: . Wolę unikać makr, , więc używam 0. Kolejny problem z NULL polega na tym, że ludzie czasami błędnie uważają, że różni się on od 0 i/lub nie jest liczbą całkowitą. W przedstandardowym kodzie , NULL był/jest czasami określany jako coś nieodpowiedniego i dlatego miał/musi być unikany. To mniej powszechne w tych dniach . Jeśli musisz wymieniać wskaźnik zerowy na , wywołaj go nullptr; to, jak to się nazywa w C++ 0x. Wtedy "nullptr" będzie słowem kluczowym .

8

Czym dokładnie jest problem z coraz NULL skąd jesteś ma ?, czyli

#include <stddef.h> 

lub

#include <cstddef> 

jak wspomniałem w odpowiedzi @Johannes Rudolfa każde oszustwo nie jest prawdopodobne, że będzie to bardzo przyszłościowe w obliczu takich rzeczy jak nullptr itp.

EDYCJA: podczas gdy stdlib (i wiele innych) jest wymaganych do włączenia NULL, stddef jest najbardziej kanonicznym nagłówkiem [i był przez dziesięciolecia].

PS Ogólnie rzecz biorąc, złym pomysłem jest angażowanie się w tego rodzaju sztuczki, chyba że masz naprawdę dobry powód. Nie rozszerzyłeś myślenia, które doprowadziło cię do poczucia potrzeby zrobienia tego. Jeśli mógłbyś dodać trochę szczegółów, to prawdopodobnie doprowadzi to do lepszych odpowiedzi. Inne osoby, które odpowiedziały na to pytanie, powinny również wskazać to w swoich odpowiedziach, ale przypuszczam, że FGITW jako FGITW radzi sobie najlepiej: D

EDYCJA 2: Jak zauważył @Yossarian: Jedynym usprawiedliwieniem jest to, że nie istnieje wartość NULL zdefiniowana w niezgodnie z językowymi formami w innym miejscu w systemie. Naga kompilacja bez nagłówków i/lub jeśli piszesz własną niestandardową bibliotekę standardową od podstaw, są przykładami takiej sytuacji. (W takim scenariuszu z czystą skórką poleciałbym z odpowiedzią @ lilburne'a (pamiętaj, aby używać jak najwięcej 0))

+1

+1 za sugerowanie, aby przejść do standardu – legends2k

+0

@ legends2k: Wydaje się oczywiste dla mnie (i @Neil Butterwort h w komentarzach do pytania, ale nikt nie dał mi tego wcześniej), ale myślę, że ludzie lubią rozwiązywać zagadki, których nie trzeba rozwiązywać. –

+0

@Ruben: Programiści, widzicie;) – legends2k

1

Myślę, że każdy, kto nie wie, że ustawienie wskaźnika w C/C++ 0 oznacza to samo, co ustawienie NULL, nullptr lub jakikolwiek inny odpowiednik nie powinien mieszać się do kodu. Różnica między czytelności

char* ch = NULL 

i

char* ch = 0; 

jest minimalne. Jeśli chodzi o wyrażenia formy

if (NULL == ch) { 
} 
if (0 == ch) { 
} 
if (nullptr == ch) { 
} 

nie są bardziej czytelne niż

if (!ch) { 
} 
+0

@lilburne: Przeniesienie nullptr na twoje przykładowe rzeczy, zamiast je wyjaśniać. nullptr ma cel i nie zawsze jest w 100% wymienny z NULL. Zgadzam się jednak z ogólną zasadą, że dla większości zastosowań należy rozważyć preferowanie '0' i niejawnej koomery do int do' NULL'. (Ale nie otrzymuję +1 ode mnie, gdy konfrontuje się z tymi problemami: D) –

0

W przeciwieństwie do tego, co niektórzy ludzie tutaj stwierdzić, 0 jest całkowicie poprawny definicja NULL w C. Tak więc trzeba zachowaj ostrożność, gdy podajesz NULL jako argument funkcji zmiennej, ponieważ może ona zostać pomylona jako wartość całkowita 0, kończąca się niepowodzeniem.

http://c-faq.com/null/null2.html

BTW, comp.lang.c FAQ jest bardzo polecany odczytu dla każdego programisty C. Zobacz na przykład tutaj:

http://c-faq.com/null/null1.html

zawierających takie perełki prawie zapomnianej mądrości w rodzaju „Jak wspomniano powyżej, jest zerowy wskaźnik dla każdego rodzaju wskaźnik, a wartości wewnętrzne null wskaźniki dla różnych typów mogą być różne." Co oznacza, że ​​calloc lub memset NIE są przenośną inicjalizacją dla wskaźników.

1

Nie rób tego. Nic nie mówi, że NULL musi być wartością zerową, jest to specyficzna implementacja.

Może to być wartość reprezentująca koniec pamięci, specjalne miejsce w pamięci lub nawet obiekt reprezentujący brak wartości.

Takie postępowanie jest bardzo niebezpieczne, może przerwać przenoszenie i na pewno wkręci się przy pomocy edytorów kodu. Nie kupuje cię nic, zaufaj definicji swojej biblioteki.

EDYTOWANIE: Evan ma rację! Sam kod mówi zero, pod maską kompilator może robić, co chce, z konkretnymi szczegółami dotyczącymi implementacji. Dzięki Evan!

+1

jest to powszechna błędna interpretacja normy. Stała wskaźnika zerowego ** wynosi ** 0. Jednak wartość wskaźnika pustego (nienaświetlona na poziomie języka, więc nigdy nie stanowi problemu) może być specyficzna dla maszyny. C99 standard 6.3.2.3: "Ciągłe wyrażenie o wartości całkowitej z wartością 0, lub takie wyrażenie rzutowane na typ void *, jest nazywane zerową wartością wskaźnika.55) Jeśli stała wskaźnika zerowego jest konwertowana na typ wskaźnika, wskaźnik wynikowy, zwany wskaźnikiem zerowym, gwarantuje porównywanie nierówności ze wskaźnikiem dla dowolnego obiektu lub funkcji. " Co zasadniczo mówi "0 używane w kontekście wskaźnika jest NULL". –

+0

Zobacz również: http://stackoverflow.com/questions/1642763/null-pointer-equivalence-to-int/1642776#1642776 i http://stackoverflow.com/questions/423823/whats-your-favorite-programmer- ignorance-pet-peeve/1331729 # 1331729 i http://c-faq.com/null/machnon0.html –

+0

@Walt: nie ma problemu, usuniemy teraz moje -1 :-). –

0
#define NULL 0 //for C 

jest doskonałe określenie w C

np

char *ch = NULL ; 
*ch++ ;// will cause error 

powoduje błąd ponieważ ch skierowaną do niczego podczas wykonywania oświadczenie przyrost jest znana przez kompilator widząc wartość wskaźnika w tabeli przeglądowej być 0

jeśli u próby aktualizacji tego wskaźnika następnie w rzeczywistości zmieniasz zawartość regionu CODE , który zaczyna się od adresu fizycznego 0. Z tego powodu pierwszy wpis z tablicy stron przed regionu kodu zaczyna utrzymywana jest pusty

Czym dokładnie jest problem z coraz NULL skąd jesteś ma ?, czyli

#include <stddef.h> 

lub

#include <cstddef> 

jak wspomniałem w odpowiedzi @Johannes Rudolfa każde oszustwo zrobić, to nie może być bardzo przyszłościowe w obliczu rzeczy jak nullptr itp

EDYCJA: podczas gdy stdlib (i wiele innych) jest wymaganych do włączenia wartości NULL, stddef jest najbardziej kanonicznym nagłówkiem [i był przez dziesięciolecia].

PS Ogólnie rzecz biorąc, złym pomysłem jest angażowanie się w tego rodzaju sztuczki, chyba że masz naprawdę dobry powód. Nie rozszerzyłeś myślenia, które doprowadziło cię do poczucia potrzeby zrobienia tego. Jeśli mógłbyś dodać trochę szczegółów, to prawdopodobnie doprowadzi to do lepszych odpowiedzi. Inne osoby, które odpowiedziały na to pytanie, powinny również wskazać to w swoich odpowiedziach, ale przypuszczam, że FGITW jako FGITW radzi sobie najlepiej: D

EDYCJA 2: Jak zauważył @Yossarian: Jedynym usprawiedliwieniem jest to, że nie istnieje wartość NULL zdefiniowana w niezgodnie z językowymi formami w innym miejscu w systemie. Naga kompilacja bez nagłówków i/lub jeśli piszesz własną niestandardową bibliotekę standardową od podstaw, są przykładami takiej sytuacji. (W takim scenariuszu z czystą kością podążałbym za odpowiedzią @ lilburne'a (pamiętaj, aby użyć 0 w miarę możliwości))

Powiązane problemy