Article View: pl.comp.lang.c
Article #936malloc czy (type *)malloc?
From: Marek Kotowski
Date: Mon, 26 Jan 1998 15:43
Date: Mon, 26 Jan 1998 15:43
140 lines
6064 bytes
6064 bytes
Karpierz wrote:
>> Niech Pan sie nie dziwi. Nie wszyscy sa tacy lotni jak
>> Pan. :-)
> Widze ze zaczynasz (Pan) coraz bardziej "merytoryczna" dyskusje...
> To miala byc zlosliwosc lepiej wiedzacego ??? smutne...
To nie miala byc zlosliwosc. Jesli Pan to tak odebral,
bardzo przepraszam. Uwagi takie, przynajmniej w dyskusji
z Panem, juz sie nie powtorza.
>> BTW - nie musi Pan stosowac rzutu przy wywolaniu malloc.
>> Jest to zbedne, a nawet niewskazane.
> Oooo :) czepiamy sie !
Tez nie. Po prostu, rzutowanie takie jest bardzo czesto
traktowane przez programistow jako obligatoryjne i uznalem,
ze mozna podkreslic, ze jest ono zbedne i niewskazane.
Wiecej: uznalem, ze rzecz jest na tyle typowa, ze nalezy
ja ujac w oddzielnym postingu.
> Tak :) ? A to mnie ubawiles (Pan) :).
> Wszedzie w ksiazce K&C jest stosowane takie rzutowanie i tez
> bylem przekonany ze wlasnie tak jest bardziej prawidlowo, a tu
> masz.. taka wolta.. nawet niewskazane...
> Prosze o uzasadnienie.
Pomine niemerytoryczna uwage o ubawieniu. Oto uzasadnienie:
1. Co do K&R (rozumiem, ze K&C to po prostu literowka):
Ja nie mam przed soba teraz ksiazki K&R, ale tam,
o ile dobrze pamietam, funkcja malloc byla typu
char * (podobnie bylo w innych starszych kompilatorach).
Tak czy inaczej, w wersji K&R nie bylo typu void *.
Dlatego uzywano rzutu.
2. Funkcja malloc jest typu void *. Na mocy definicji
wskaznik taki spelnia najsilniejsze warunki ulozenia
obiektow w pamieci i moze byc przypisany kazdemu innemu.
Zatem rzut przy malloc jest zbedny. W istocie konstrukcja
SomethingPtr = malloc(sizeof(SOMETHING));
lub klasyczniej:
if ((SomethingPtr=malloc(sizeof(SOMETHING))) == NULL)
...
jest idiomem jezyka C. Rzut przy malloc, jak wiekszosc
rzeczy zbednych, zaciemnia kod. Tak samo jak zaciemniaja
kod np. zbedne nawiasy w wyrazeniach, ktore sie czesto
wstawia, bo sie nie zna dostatecznie priorytetow operatorow.
3. Jest jeszcze jedna, byc moze istotniejsza przyczyna,
dla ktorej nie nalezy rzutowac wartosci zwracanej przez
malloc. Otoz kasuje to - czy tez moze kasowac - ostrzezenie
kompilatora o braku pliku definicyjnego z prototypem malloc,
jesli pliku takiego do modulu nie wlaczono. W takiej sytuacji
kompilator sam zbuduje sobie prototyp funkcji malloc na podstawie
jej wywolania i nada jej domyslny typ int. Jesli w przypisaniu
wartosci zwracanej przez malloc zmiennej wskaznikowej
nie bedzie rzutu, kompilator rzecz oprotestuje, piszac np.
"nonportable pointer conversion" (wartosc calkowita jest
przypisywana wskaznikowi). Jesli rzut przy malloc bedzie,
kompilator uzna, ze programista wie, co robi (zaznacza to
przeciez za pomoca rzutu) i nie wypisze takiego komunikatu.
W rezultacie na skutek rzutu moze zostac przeoczony blad
niewlaczenia do modulu odpowiedniego pliku definicyjnego.
4. Uprzedze od razu argument, ze rzut przy malloc wyjasnia
intencje programisty. Tak sie czasami sadzi, mowiac np, ze.
p = (char *)malloc(100);
wyjasnia, na co alokowana jest pamiec. Jest to chybiony argument,
bo rzecz tu jest w samej nazwie zmiennej wskaznikowej, ktora
powinna wyjasniac nature wskazywanego obiektu. Byloby lepiej,
gdyby miala ona odpowiednia nazwe, np.
SOME_STRUC *SomeStrucPtr;
...
if ((SomeStrucPtr=malloc(sizeof(SOME_STRUC))) != NULL)
...
Nie ma rzutu przy malloc, ale intencje sa jasne i wiadomo,
o co chodzi.
5. Brak rzutu przy malloc jest zgodny ze standardem,
wiecej: z jego duchem. Po to wprowadzono miedzy innymi
jasne zasady rzutowania wskaznikow w standardzie,
by nie trzeba bylo w takich sytuacjach stosowac rzutow.
> Osobiscie wszystkim zalecam wlasnie stosowanie rzutowania.
Coz, kazdy zaleca to, co uwaza za wskazane. Moim
zdaniem rada Panska jest zla. Rzecza czytelnikow
jest osadzic, ktore zalecenie jest bardziej racjonalne.
> Dlaczego ?
> Podam tylko jeden prosty przyklad, na tyle malo teoretyczny
> co bardzo zyciowy:
> char * x = malloc (123);
> Pod C sie kompiluje ? rzeczywiscie... No to piszemy "krocej"...
> Po co sie meczyc... Po kilku latach stwierdzamy ze mamy
Nie chodzi o meczenie. Chodzi o zasade stylistyczna.
> juz kilka MB kodu w C...
> No tak, ale te obiekty i to C++. Wypada sprobowac.
> cannot convert void * to char * !
> lub tym podobnych.
To prawda. Kompilator C++ tak zareaguje w tym przypadku.
Ale C++ jest innym jezykiem niz C. To, co Pan - byc moze nie
do konca swiadomie - sugeruje, to wziac modul napisany w C, nadac
mu rozszerzenie CPP i kompilowac jako C++. To tez, moim zdaniem,
zla rada. C i C++ to sa inne filozofie programowania.
Jezyk C jest do programowania strukturalnego, C++ - do
obiektowego. Jesli Pan ma duzo kodu w jezyku C, to, owszem,
mozna go wykorzystac w projekcie programistycznym w C++,
ale jako moduly w C wlasnie, a nie jako kod w C, ktory ma
stac sie kodem w C++ (program strukturalny nie stanie sie przez
to obiektowym). Nie nalezy tez kodujac w C, myslec,
czy kupi to kompilator C++, bo wtedy grozi programiscie
swoista schizofrenia: czy ten kod w C akceptuje kompilator C++,
czy nie? A jezeli kod napisany w C jest zgodny z wymogami C++,
to czy jest to C, czy moze juz C++? A moze to juz jest nawet
programowanie obiektowe? :-)
I tyle. Takie sa Panskie rady (moim zdaniem zle) i argumenty,
a takie sa moje. Reszte zostawmy Czytelnikom.
Pozdrawiam
Marek Kotowski
Technical Details
Message-ID:
<34CCAF18.4877@imm.org.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!pingwin.icm.edu.pl!news.icm.edu.pl!news.nask.pl!not-for-mailShow Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!pingwin.icm.edu.pl!news.icm.edu.pl!news.nask.pl!not-for-mail From: Marek Kotowski <mkot@imm.org.pl> Newsgroups: pl.comp.lang.c Subject: malloc czy (type *)malloc? Date: Mon, 26 Jan 1998 16:43:21 +0100 Organization: Instytut Maszyn Matematycznych Lines: 140 Message-ID: <34CCAF18.4877@imm.org.pl> NNTP-Posting-Host: 148.81.238.53 Mime-Version: 1.0 X-Mailer: Mozilla 3.01Gold (Win95; I) Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit