🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.lang.c
Article #961

Re: malloc czy (type *)malloc?

#961
From: Michal Malecki
Date: Tue, 27 Jan 1998 13:10
186 lines
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-mail
References: <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