Üdv!
C/C++/Obj-C-ben irogatok programokat mostanság (C# felől érkezvén), és még senkinek sem kellett belenyúlnia ezekbe, ám ez nem marad mindig igy. Van egy (valószinűleg) mások számára elég idegesitő, ámde mindig konzisztensen követett stilusa annak ahogy a kódot irom:
int kever(pakli* a)
{
TAB kód;
TAB kód;
}
Ebben ugye két dolog van amit úgy látom a "profik" nem igy csinálnak: a pointer csillagozása, illetve a kapcsoszárójelek. A kapcsos zárójelről csak annyit, hogy szerintem ez inkább egyéni preferencia kérdése, és szerintem igy sokkal átláthatóbb. Na de a pointerek.
Egyszer tudom azt, hogyha ezt csinálom:
int* p1, p2;
akkor a p2 nem lesz pointer. Ez lehetne indok arra hogy inkább ne oda tegyem. De! Nekem valami filozófiailag bűzlik ezzel. Mert ha én deklarálok valamit, akkor:
TIPUS NÉV;
formában teszem. Márpedig p1 tipusa nem int, hanem int* - vagyis int-re mutató pointer.
Egyébként én pont emiatt kerülöm is az ilyen csoportos deklarációkat. Egyszerűen nem értem ezen kivül mi oka kell legyen annak, hogy a deklarációban máshová tegyem a csillagot.
Idegesiti-e vajon a kódomat néző többi embert ha ez a kód igy van formázva? Mert őszintén szólva engem idegesit a "szabványos" verzió. Ti milyen módon formázzátok a kódotokat?
Hozzászólások
valoban helytelen ugy
--
When in doubt, use brute force.
a * mar nem a tipus resze. ahogy csinalod, az meg szornyu.
nincs "int*" tipus, erted..
en ugy szoktam, hogy mindenutt tabolok, mindenutt (1 sorhoz is!) kirakom a { es }-t, a metodus szignatura-deklaraciojaval egy sorban kezdem a torzset. (ugyanez igaz osztalyra is)
Hát inkább a típus része, semmint a névé.
Amúgy ez egy egész aranyos leírás.
> Hát inkább a típus része, semmint a névé.
"TIPUS NEV;" , amikor az értékre van szükséged, írd le a "NEV"-et.
"TIPUS *NEV;", amikor az értékre van szükséged, írd le a "*NEV"-et.
Szóval a "pointerség" az a névhez kapcsolódik, aszerint hogy a név közvetlenül (nem pointerként) vagy közvetve (pointerként) hivatkozik az értékre. Szerintem.
De amúgy ahány nyelv, annyi szokás.
Elég szubjektív végül is, igaz.
Ha Stroustrup bácsihoz visszamegyünk, ő bizony azt írja:
"For a type T, T* is the type ‘‘pointer to T.’’ That is, a variable of type T* can hold the address of an object of type T."
Tehát kicsit nyakatekerten ugye, de létezik olyan, hogy T* típus.
(És igen, ő végig a ‘‘T* valtozo‘‘ kombinációt használja.)
Más: gyakran függvénydeklarációkban elhagyjuk a paraméterek nevét. Azaz a void fgv(T p); helyett csak egy void fgv(T); illetve mutatók esetében void fgv(T * p); helyett void fgv(T*); lesz. Vagyis egyszerűen csak típusmegjelölés.
Többféleképpen lehet értelmezni a mutató filozófiát, de a fentiek alapján nekem mindig is típus közelibb lesz. :)
> Tehát kicsit nyakatekerten ugye, de létezik olyan, hogy T* típus.
Nincs ellenemre ez a felfogás, de sajnos a szintakszis nem ennek megfelelően lett kialakítva. Nézzünk egy példát:
A példából jól látszik, hogy a 'v2' az egy 'T' típusú érték neve, a 'p1' pedig egy 'T' típusú érték névének a neve. A '*' az egy operátor, ami egy név nevéből (p1) egy érték nevét (*p1) előállító műveletet jelöl. Az '&' operátor említendő még itt, ami egy érték névéből nevet előállító operátor.
Kicsit nyakatekert ez a "név neve" dolog, tán nem is tudtam érthetően leírni, de legalább összevág a szintakszissal.
> Vagyis egyszerűen csak típusmegjelölés.
A paraméter nevének elhagyása, az egyszerűen csak névelhagyás. Az hogy a név elhagyható, nem jelenti azt hogy a maradék szövegrész szintaktikailag egyetlen egységet kéne hogy képezzen (egy T* típusmegjelölést).
> de a fentiek alapján nekem mindig is típus közelibb lesz.
Nem gond, úgyis csak az számít, hogy ha kódot írsz, az működik-e vagy sem.
"> Tehát kicsit nyakatekerten ugye, de létezik olyan, hogy T* típus.
Nincs ellenemre ez a felfogás, de sajnos a szintakszis nem ennek megfelelően lett kialakítva. Nézzünk egy példát:"
A szintaxis szerintem csak azért olyan, hogy megőrizze a C-vel való kompatibilitást.
KisKresz
"A paraméter nevének elhagyása, az egyszerűen csak névelhagyás. "
Hat erted, ez az. :) A nevet el lehet hagyni, a tipust nem. Ha van * vagy &, akkor azt sem.
Ergo a * es az & jobban kozelit a tipushoz, mint a nevhez. :)
> Ergo a * es az & jobban kozelit a tipushoz, mint a nevhez.
Akkor a kifejezésben előforduló '*' és '&' nem ugyanaz, mint a deklarációban előforduló.
Ellenben a névhez kötődő '*' és '&' ugyanazt jelentik, akár deklarációban, akár kifejezésben fordulnak elő.
Ezekben a deklarációkban mi a típus, amihez szerinted a '*' kötődik?
A példákban jól látszik, hogy a '*' a zárójelek miatt nem kapcsolódhat semmi máshoz, csak a 'disp' és az 'op' nevekhez. A zárójelek alkalmazása nem meglepő, ha a '*' egy operátor, aminek precedenciája van.
Mas vegerol kaptad el a temat ugy tunik.
Elismerem, aranyos ez a fuggvenymutatos pelda, de az is biztos, hogy 100 esetbol 90-szer nekem a hagyomanyos mutatos elgondolasok jutnak eszembe, amiket feljebb is irtam.
Ne keverjuk!
Van a deklaracio, ahol leirod a tipust, pl. int*
Es van a definicios reszben a * (azt hiszem, dereferencia nevu) operator, amivel a pointer altal mutatott ertekhez fersz hozza.
Rakjatok ra egy typedef-et oszt csa.
--
Pedig de. C++-ban az összes *, &, const, és volatile a típus része. Ld. pl.
std::set<Z*>
Ezért hát +sok az int*-nak, C++-ban legalábbis mindenképp. De ha mutatsz olyan cpp projektet, ahol nem így használják, az érdekel.
nem vagyok C++ guru, szoval tevedhettem is. :)
de ha a tipus resze lenne, akkor kutya kotelessege lenne az int* a, b deklaracio utan a b-nek is mutatonak lennie.
Igen, de sajnos C kompatibilitás szopó.. marad a typedef.
igy van.
a typedef tipus* pojnter;
pojnter a, b;
eseten meg azert lesz mindketto pointer, mert a typedef kulon hat a valtozokra, mintha egyesevel irtad volna.
Imadom.
--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.
> int* p1, p2;
"Every declaration should be for a single variable, on its own line, with an explanatory comment about the role of the variable. Declaring multiple variables in a single declaration can cause confusion regarding the types of the variables and their initial values. If more than one variable is declared in a declaration, care must be taken that the type and initialized value of the variable is known." (CERT Secure Coding Standards)
Azért ezzel nem tudok egyetérteni: "with an explanatory comment about the role of the variable"
Mert ugye két dolog lehetséges:
Na törjön le az ilyen keze.
Ha viszont:
akkor tökéletesen felesleges a komment.
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
> int numOfAnyamkinnya; // Number of Any
> akkor tökéletesen felesleges a komment.
Azért az némi magyarázatot igényelhetne, hogy miért "sima" int, és nem unsigned int. Vagy hogy lehet-e == 0.
A kommenteknek nem az a lenyege, hogy mi van ott a kodban, hanem miert van ott.
http://www.codinghorror.com/blog/archives/000749.html
A kapcsos zárójelekkel mi lenne a gond?
Ami a *-ozást illeti, én is így jelölöm, én is így látom logikusnak!
Nem így kéne, ez rendben van, de pl. hogy néz ki ha referenciaként használunk egy függvényben tömböt?
int fvNeve(int *&tomb) {
}
Ez így nem ocsmány? :)
Egyébként én is ma indítottam hasonló topicot, indentation-ökről, kapcsoszárójelekről.
És arra a következtetésre jutottam, hogy fölösleges "szabványos" módon programozni.. (márha lennének egyáltalán szabványok).
K&R vagy ANSI ha C++-ról van szó, és TAB vagy SPACE.
Ma reggel még úgy gondoltam hogy mától Stroustrup módra fogok C++-ban programozni, de amint belelapoztam a könyvbe, láttam hogy hányaveti átgondolatlan a kód kinézete.
Például:
case Lexer::NAME:
{TAB double &v = table[Lexer::ASSIGN) v = expr(true);
TAB return v;
}
Rendben, ha valaki kulon sorba szereti a kapcsos zárójelet .. de abba a sorba minek ír ??
A zárójelezés már a suliban jelen lévő dolog volt: van aki sűrűn, valaki szellősen írt jegyzetből szeret tanulni. Sztem ez ugyanerről szól.
Nem vagyok benne biztos, hogy nem fordításkor keveredett ez bele...
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
+++
Nem az első kiadásnál jár már a könyv, és nem is mondanám, hogy hányaveti az ürge. :)
És arra a következtetésre jutottam, hogy fölösleges "szabványos" módon programozni.. (márha lennének egyáltalán szabványok).
Kivéve ha a kedvenc szövegszerkesztőd kedvenc nyelvi támogató modulja szigorúan egy formázást támogat.
Pocsek szovegszerkeszto lehet...
--
C#-ban tudomásom szerint referenciák vannak, és nem pointerek, akkor a C++ nyelv esetén miért ragaszkodsz a pointerekhez? Felesleges, sőt, helytelen gyakorlat. A referencia biztosan mutat valahova (létező, azonos típusú objektumra), a pointer meg leginkább oda, ahova (nem) akarom.
Ez most komoly?
while (!sleep) sheep++;
Kutyafuttában írtam, ha esetleg rövidnek találod, ezért van. Mi a baj vele?
Formázásról meg teljesen értelmetlen beszélni, az a lényeg, hogy aki írja, el tudja olvasni. Ha meg nem egyedül írja a kódot, akkor meg vannak megegyezésen alapuló formázási stílusok (pl. K&R legtöbb esetben, kivéve...).
Hogy a címhez kapcsolódjak: a T* az ideális választás, mert ha a "T* a" vagy "T *a" után az "a" változóval dolgozol, akkor annak a típusa egy T-re mutató pointer, azaz "T*". Ezért idegen számomra még mindig a "T *a", ami meg C-ben gyakori.
Csak a hozzaszolasodbl ugy tunt, mintha a pointereket mindenhol lehetne / erdemes lenne helyettesiteni referenciaval C++-ban, ami azert nincs feltetlen igy.
while (!sleep) sheep++;
Lényegében minden függvényparaméter esetén érdemes helyettesíteni referenciával. A konkrét példában határozottan ebben a kontextusban szerepelt. Persze, nem minden esetben működik e megoldás, például sztringeket (karaktertömböket) csak mutatóként lehet átadni, vagy pedig std::string-re konvertálva referenciaként, de ez utóbbi elég ronda.
A referenciával van egy olyan gond, hogy nem látszik hívásakor, hogy az adott változó megváltozhat a fv hatására.
Emiatt pl Qt-ben minden constref ami lehet, és mutató ami megváltoztatja az argumentumot.
Nekem ez kicsit idegen, többnyire elfelejtem (kevés ilyen van), de van benne logika...
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
Több, mint tíz éve C++-ozok, de nekem speciel tökmindegy, hogyan van indentálva egy kód, hol a csillag, stb. Nekem konkrétan annyi igényem van, hogy legyen konzisztens egy projekten belül.
Én pont így használom ahogy te.
Egyébként meg tökmindegy, csak konzisztens legyen projekten belül. Ha te kezdted a projektet te dirigálsz, ha máshova kontárkodsz, kövesd az ottani szokásokat.
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
Én is int*-ot írok, dolgoztam projektben, ahol mindenki így tett. Meg olyanban is, hogy egyedül én írtam így.
Tök mindegy. El fogják tudni olvasni így is, úgy is.
Sőt, akkor is, ha int * p1-et írsz.
És én is pont azért csinálom így (meg mindenki, aki ugyanígy írja), mert úgy gondolják, hogy int* az az int-re mutató pointer típus, és p1 a változó.
*p1 meg az értéke (p1 változóból a * operátor kiveszi a zokszigént)
G
Hmmm én is programozok C-ben (bár magamtól tanultam senki sem segített, így tuti vannak hibáim) azt hittem eddig, hogy a kettő ekvivalens:
int* p1, p2, p3;
int *p1, *p2, *p3;
Mondjuk ez eddig nekem hibát nem okozott, mert én mindig a 2. megoldást használtam. Nekem jobban tetszik, ill. kevésbé valószínű, hogy tévedek.
mert a 2. a helyes, HA 3 pointert akarsz.
A * a változóra hat, nem a típusra. Azért lehet a *-ot hozzáírni a típushoz, mert a szabvány megengedi (pedig csalóka).
--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.
Az első esetben int*, int, int jön létre.
A másodikban int*, int*, int*.
Nem ekvivalensek.
Igen már tudom. Ugyan olyan mintha:
int *p1, p2, p3; Szerncsére csak magamnak progamozok ( C-ben, közözben Delpizni kell :( ), és mindíg a 2. utat használtam. Szóval véletlenül a jót.
Figyelj!
Szokd meg, hogy egy sorban egy valtozot deklaralsz, es nem lesz semmi gubanc
Raadasul meg a kod is olvashato lesz.
Milyen fasza lenne, ha lehetne zarojelezni ;) azaz a
ekvivalens lenne a
sorral.
typedef int* int_ptr;
int_ptr p1, p2, p3;
typedef void* pointer
lolz, lattam valahol ilyet
--
When in doubt, use brute force.
Haha, epic typedef:))
glib-nek hívják. És persze micsoda dolog elhagyni a "g" betűt, ami nem "g"-vel kezdődik... na olyan nincs. Tehát:
typedef void* gpointer;
;)