Article View: pl.comp.lang.c
Article #961Re: malloc czy (type *)malloc?
From: Michal Malecki
Date: Tue, 27 Jan 1998 13:10
Date: Tue, 27 Jan 1998 13:10
186 lines
9025 bytes
9025 bytes
Marek Kotowski <mkot@imm.org.pl> wrote cos, czego nie moglem zostawic bez
odpowiedzi:
: Karpierz wrote:
:>> 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.
: 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.
Jasna sprawa. Jednak sprawa sie komplikuje, jezeli chcemy miec do czynienia
z C++...
: 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.
Oj, bylbym na panskim miejscu ostrozniejszy z takimi teoriami!
W kazdym razie na pewno kompilator (dobry kompilator!) wygeneruje dwa
ostrzezenia:
1. Wywolano funkcje nie posiadajaca prorotypu.
2. Uzyto nielegalnej konwersji z (int) na (char*) [np.]
Prosze wiec nie mowic o niebezpieczenstwach. Programista powinien zwracac
uwage na takie ostrzezenia i ZAWSZE wlaczac pliki naglowkowe (albo pisac
jawnie naglowki samemu). Zaznacze tu tylko, ze C++ akurat nie dopuszcza
wywolania funkcji nie posiadajacej prototypu.
: W rezultacie na skutek rzutu moze zostac przeoczony blad
: niewlaczenia do modulu odpowiedniego pliku definicyjnego.
I ten blad panskiego rozumowania chcialem wytknac.
: 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.
A tu sie zgadza!
Linijka przez pana zacytowana swiadczy TYLKO I WYLACZNIE o glupocie progra-
mujacego. Bo jezeli juz to piszemy albo:
p = malloc( 100*sizeof (char) );
albo
p = calloc( 100, sizeof (char) );
W innym wypadku mowienie ze wyjasnia to intencje programisty jest idiotyzmem.
: 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.
Niby po co ? W standardzie C rzutowanie wskaznika void* nigdy nie jest
konieczne. Co innego C++, o ktorym zaraz napisze.
: 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
:> 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.
Ano wlasnie.
Powiedzcie mi panowie: KTO PRZY ZDROWYCH ZMYSLACH uzywa w programie w C++
funkcji malloc!?
Z operatorem new jest taki akurat dowcip, ze zwraca on co prawda typ void*
(vide: przeciazanie operatora new), ale nie wymaga nigdy konwersji.
Poniewaz C++ jest jezykiem o silnej typizacji, takie numery nie moga byc
dozwolone. I w praktyce niestey nie nalezy stosowac w C++ funkcji malloc,
tylko operator new. Jezeli komus koniecznie zalezy na stosowaniu malloc,
to powinien przeciazyc operator new. Dlaczego ?
Zarowno new jak i malloc dokonuja konstrukcji obiektu. Jednak...
Funkcja malloc robi to zle. Jedyne bowiem co robi to przydziela pamiec.
Podam dwa przyklady, dowodzace, ze w C++ nie nalezy stosowac malooc:
1. Jezeli np. klasa Klocek jest abstrakcyjna, to po deklaracji:
Klocek* pk;
kompilator odrzuci stanowczo:
pk = new Klocek;
ale nie ma powodu, by odrzucic:
pk = (Klocek*) malloc( sizeof (Klocek) );
Moze to spowodowac trudne do wykrycia bledy.
2. Jezeli klasa Klocek ma konstruktor z parametrami, to w jaki sposob
poda sie owe parametry ? No ? Slucham uprzejmie. A co jezeli klasa NIE
ZAWIERA konstruktora bezparametrowego ? Znow:
pk = new Klocek;
kompilator odrzuci, bo konstruktor ma niewlasciwe parametry. Jednak
pk = (Klocek*) malloc( sizeof (Klocek) );
konstruktor nie odrzuci, bo nie traktuje tego jako konstrukcje obiektu.
A jak w przyszlosci komus sie pomysli, zeby np. odrzucac proby odwolania sie
do nieskonstruowanego obiektu ? Wtedy nawet jezeli przydzieli sie pamiec
funkcja malloc, to kompilator stwierdzi, ze "nie przydzielono pamieci na
obiekt - dziekuje za uwage" (oczywiscie moze zrobic taki numer tylko na
zmiennych referencyjnych).
Dlatego tez od razu stwierdzam: malloc stosujemy w C, a w C++ new.
A skoro malloc jest tylko dla C, to mnie wisi i powiewa co na to powie
kompilator C++.
A taka mala dygresja: co zrobic jak np. ma pan program zlozony z 20 plikow,
wszystkie uzywaja pliku naglowkowego z deklaracja struktury, a jedno z pol
struktury nazywa sie 'class' ?
: 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.
I wlasnie dlatego nie nalezy przenosic takich programow "zywcem".
Jak juz, to odpowiednio taki program przerobic (jedna z tych przerobek bedzie
oczywiscie zamiana malloc na new).
: 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).
Tu zaczyna pan zlekka przeginac. Czyzby pan sugerowal, ze C++ nie nadaje sie
do programowania strukturalnego ? Ale jak najbardziej sie nadaje!
IMHO jezyk C nadaje sie WYLACZNIE dla ludzi, ktorzy nie potrafia zrozumiec
jezyka C++. Kazdy program, zamierzony do napisania w C, mozna napisac w C++
(a nawet lepiej go w tym jezyku napisac!). Przeciez nikt nie kaze stosowac
programowania obiektowego w C++! Przeciez ma on poza obiektami tyle mozliwosci
i udogodnien, ze ja np. jak chce napisac jakis program to nawet nie mysle o
tym, zeby uzyc do tego czystego C.
: 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? :-)
Moze wyjasnijmy sobie co to bedzie programowanie obiektowe ? Czy polega na
uzywaniu obiektow ze standartowej biblioteki, czy tez deklarowaniu wlasnych ?
Jezeli uzywa sie np. jedynie obiektow z biblioteki iostream, czy fstream, to
IMHO to nie jest jeszcze programowanie obiektowe. Natomiast np. pisanie
programow pod biblioteka OWL to juz jest.
: I tyle. Takie sa Panskie rady (moim zdaniem zle) i argumenty,
: a takie sa moje. Reszte zostawmy Czytelnikom.
Zwlaszcza przystosowywanie malloc do wymogow C++.
Pozdrawiam serdecznie,
--
.---. . . - Michal Malecki <mmalecki@technologist.com>/The things that
\___ ,-. | , |- ,-. ,- mUd: zly.mud.org.pl 4000. /can't destroy you
\ |-' |< | | | | uRl: www.kis.p.lodz.pl/~sektor /make you
`---' `-' ' ` `' `-' ' pGp: sektor@zly.kis.p.lodz.pl /stronger...
Technical Details
Message-ID:
<6akmcl$nua@polonez.man.lodz.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!pingwin.icm.edu.pl!news.icm.edu.pl!ict.pwr.wroc.pl!news.man.lodz.pl!not-for-mailReferences:
<34CCAF18.4877@imm.org.pl>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!pingwin.icm.edu.pl!news.icm.edu.pl!ict.pwr.wroc.pl!news.man.lodz.pl!not-for-mail From: Michal Malecki <sektor@zly.kis.p.lodz.pl> Newsgroups: pl.comp.lang.c Subject: Re: malloc czy (type *)malloc? Date: 27 Jan 1998 13:10:45 GMT Lines: 186 Message-ID: <6akmcl$nua@polonez.man.lodz.pl> References: <34CCAF18.4877@imm.org.pl> NNTP-Posting-Host: sektor@zly.kis.p.lodz.pl User-Agent: tin/pre-1.4-980105 (UNIX) (SunOS/5.5.1 (i86pc)) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit