Tomb meret valtozobol

Fórumok

Hi,

Az alabbi dolgot szerettem volna csinalni Visual Studio 2005-os C forditoval (nem uj, de ez van hivatalosan):

int a = 5;
char array[a];

de ezt mondja:

error C2057: expected constant expression
error C2466: cannot allocate an array of constant size 0
error C2133: 'array' : unknown size

Ugyanez egy jelenlegi gcc-vel (4.4) minden extra parameter nelkul felordul.

Meg lehet ezt valahogy javitani? - Ugy ertem, lehet, hogy valami kapcsoloval mukodne?

Koszi,

/sza2

Szerk:

Nem az

int a = 5;
char *array = malloc(a);

megoldassal.

Hozzászólások

a "variable-length arrays" csak ISO-C99-ben van benne (a gcc pedig C90-ben is elfogadja, illetve c++ -ban).
A visual studio C90 fordító, így malloc nélkül ez nem fog működni neked.

Van, hogy malloc nem megengedett, pl. egyes beagyazott rendszereknel.
Amugy csak szolok, hogy a malloc() egy lassu muvelet, sot a free() is lassu, cserebe a stack-en valo foglalas nagyon gyors.

Raadasul malloc()-ot manapsag (C++11) csak a 8-bites kezdok hasznalnak (kiveve nagyon ritka eseteket): vannak kontenerek, pl vector (osidok ota). Van ezen kivul unique_ptr es shared_ptr. Olyanna lett, mint a goto: neha kell, de nagyon meg kell indokolni.

Szerintem egy modern C++ coder manapsag nem irja le, hogy malloc, csak ha nagyon nagy baj van (ertsd szar a kodbazis, rosszul terveztek meg a memoria allokocios strategiat).

A stack-en altalaban tudjuk a max meretet a tombnek, es azt foglaljuk, eszben tartva, hogy a stack kicsi.

Mindenképpen változónak (értsd: több értékadást elviselőnek) kell lennie annak a változónak? Mert ha nem, akkor dinamikus memóriafoglalás nélkül 2 megoldást is látok a problémára, az egyik C, a másik C++:


//C
#define A 5
char array[A];

//C++
const int a=5;
char array[a];

Egyszer van ertekadas, a fuggvenyek elejen, utana nem valtozik.

Igazabol valami iyesmit akartam:


fgv1() {
  int length = 5;
  char array[length];
  ...
  sendsomething(device, array, length);
}

fgv2() {
  int length = 10;
  char array[length];
  ...
  sendsomething(device, array, length);
}

fgvN() {
  int length = 1;
  char array[length];
  ...
  sendsomething(device, array, length);
}

/sza2

Ha a fuggveny elejen van mind a ket valtozo definialva, miert nem tudod beutni azt a ketto szamot megegyszer?

Mivel utana vegig a length valtozoval szamolsz, igy ha modositani kell, egy darab kozponti helyen kell modositani, igaz, ket sorban. Nem akkora hibalehetoseg...7

A masik: miert fazunk az alloca() -tol?
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

Ha egy alapvetoen specialis esetekre kitalalt eszkozt (ez itt most az alloca) elkezdesz esz nelkul hasznalni, akkor konnyen kialakulhat az a bad practice, hogy mindenhol ezt hasznalod.
Foleg ugy, hogy nem irod oda kommentben, hogy

// Mivel 5 elemu a tomb, ezt meg allokalom a stacken 

Aztan kesobb valaki fogja a kododat, esznelkul masol belole, meg se nezi, mit csinal a kod (ha hrgy84-nek jo volt, nekem is jo lesz), es megtanulja, hogy hat az alloca az milyen jo dolog, majd nekiall a stacken allokalni hatalmas tomboket.

A szakmaban nagyon sokszor viselkednek igy, foleg a kezdok: nem akarja megerteni amit csinal, csak mukodjon valahogy.
Aztan ebbol ki is alakulnak a rossz szokasok sajnos, amiket kiirtani nagyon nehez.

Azt a technikai dolgot mar emliteni sem akarom, hogy az alloca hivasa eredmenyezhet nem definialt viselkedest (amikor eppen stack overflow tortenik), azaz hibakezelest nem tudsz csinalni.

Egy eszkoz hasznalatatol nem felni kell, hanem megtanulni hasznalni.

Ha megprobalsz effektiv kodot irni, sok esetben az a vege, hogy valami specialis problemara egy specialis megoldast alkalmazol, amit nem lehet jokerkent hasznalni barhol. Ez esetben lehet batran kommentezni, foleg ha attol felsz, hogy mas vakon "atemeli" ill. valtoztatja a kododat. Ha valaki ezt ennek ellenere megteszi, akkor vegyuk ugy, hogy ez is a tanulasi fazis resze ;)

Hibakezelest akkor sem tudsz csinalni, ha alloca() helyett egy lokalis tombot hasznalsz, az ugyanugy felzabalhatja a stackedet. Emiatt kar felni tole.

Viszont toredelmesen bevallom, alloca()-t en meg az eletben nem hasznaltam lol

Nem felek en hasznalni, csak 1. nem lehet batran kommentezni, hanem KELL. Pont azert, hogy aki fel fogja hasznalni a kodot, az ne tanuljon meg semmi bad practice-t. 2. Vegyuk ugy, hoy ez a TANITASI fazis resze.

Miert ugy tortnik a programozas megismerese, elsajatitasa, mintha a kozepkorban elnenk?
A diak ellesi a nagy mesterektol a peldakat, es a sajat (es mas) karan tanulja meg, hogy valoszinuleg talan mi az, ami nem lesz rossz (nem azt, hogy mi az, ami helyes).

Nezd, engem a megbizoim azert fizetnek meg jol, mert azt varjak el, hogy en tudjak jol programozni es meg veletlenul sem azt, hogy megtanitsak olyanokat, akikre nincs eleg penzuk :p Szomoru lenne, ha abbol kellene kiindulnom, hogy baj lehet belole, ha egy lusta es kepzetlen(ebb) programozo latja (masolja, modositja, ...) az adott kodomat. Igy sosem irhatnek inline asm kodot, mert jajj mi lesz, ha senki sem _akarja_ megerteni (hiszen asm ismeret meg veletlenul sem varhato el egy C/C++ programozotol :p), vagy szamuzhetnem a longjmp()-ot is a kellektarambol, mert jajj mi lesz, ha rossz kezekbe kerul.

Nem, az alloca()-t nem _kell_ kommentezni, minthogy a malloc()-nal sem irod oda, hogy "free()-t is kell majd hivni am!". Az alloca() dokumentacioja szabadon elerheto, ha valaki olvassa a kodot es nem erti, elvarhato, hogy nezzen utana. Ha ezt nem teszi, akkor sosem lesz jo programozo, csak egy "betanitott munkas". Amiert erdemes az alloca()-t kommentezni, az inkabb az, hogy miert a stack-en allokalsz es miert nem a heap-en ...

Egyebkent az "alloca() az ordog muve es tuzzel-vassal kuzdeni kell ellene" mentalitas inkabb a kozepkort idezi, mar bocsanat :p

Egyetertek. Ha egy uj dolognal valaki nem hajlando dokumentaciot olvasni, hanem esz nelkul kezdi el hasznalni, azt paros labbal kell kirugni mindenhonnan, mert az csapnivalo programozo. Tekintet nelkul arra, hogy kezdo-e vagy sem.

Tobben tudjak itt rolam, hogy en nem igazan vagyok halado programozonak nevezheto, erosen a kezdo kategoriaba mozgok, foleg C/C++ teruleten, amihez kb. lovesem sincs, pedig ezt-azt azert csinaltam mar benne. De ha en latok egy ismeretlen fuggvenyt/osztalyt/barakarmit, akkor ragooglezok, hogy mi a kutyafule az. Es ha valaki meggooglezza az alloca-t, szerintem pont eleg oldalt fog talalni, ahol le van irva, hogy "Use with caution".

Ezzel egyutt azert annyiban egyet ertek persicsb-vel hogy annyit illik fole irni, hogy miert nem malloc. Nem azt, hogy a stacken foglalunk, mert az az alloca dokumentaciojabol kiderul. Azt sem, hogy pici a tomb, mert az meg a parameterebol derul ki. Hanem azt, hogy miert dontottunk a malloc helyett e mellett (akar csak azt, hogy a fgv tul sok ponton lephet ki, es nem egyszeru a kozos kilepesi pont megteremtese).
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

A "minek van ez" es a "abszolut kiralysag" kozt nalad nincs semmi? Nem lehet valaminek a letjogosultsagat elismerni anelkul, hogy a partjat fognam?

Szerintem sem kell tuzzel-vassal uldozni, boszorkanyokat a kozepkorban volt szokas megegetni, ma meg mar allitolag tilos. Ettol viszont meg nem valtozik az, hogy ovatosan kell hasznalni.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

Csak a teljesség kedvéért, a makrós megoldás C++-ban:


template <int L>
void fgv()	//nem volt típus megadva
{
	int length = L;	//csak a meglévő kód miatt
	char array[L];

	sendsomething(device, array, length);
}

int main()
{
	fgv<5>();	//fgv1
	fgv<10>();	//fgv2
	fgv<1>();	//fgvN

	return 0;
}

+1 lehetőség:
elágazás a méret szerint, kis méretnél lokális változó, nagyobbnál malloc; értelemszerűen a végén csak akkor kell felszabadítás, ha volt malloc. (Ja, és a 'függvény közepéből return' dolgot hanyagoljuk, ronda gányolás;)


void fun (int n)
{
    char sbuff [256];
    char *p0;
    BOOL fAlloc;

    if (n > sizeof (sbuff)) {
	p0 = malloc (n);
	fAlloc = TRUE;
    } else {
	p0 = sbuff;
	fAlloc = FALSE;
    }
    ...
RETURN:
    if (fAlloc) free (p0);
}

Evvel mi mellett szeretnél érvelni? Hogy evvel az erővel sose használjunk malloc-ot, vagy sose használjunk elágazásokat? :) Egy kód bonyolultsága és átláthatósága nem teljesen függ egymástól.

Amúgy de, gotoval pont jól meg lehet csinálni az egyetlen kilépési pontot, ha éppen úgy az átláthatóbb.

--

Ne áruld el senkinek, csak magunk közt mondom: a C++-ban pont az a jó, hogy abban mindentt lehet: egy olyan úniója egészen különböző koncepcióknak, hogy ahhoz képest a kacsa-sün-páva(*) egy teljesen normális állatfajta.

(*) Aki nem tudja, mi az, a szüleitől kérdezze meg.

Őszintén szólva nem tudom. Most újra elolvastam az előző hozzászólásodat, és el kell ismerjem, hogy túl bonyolult nekem (ebben a központozás hiánya is szerepet játszhat) -- az előbb úgy értettem, hogy C++ nem lehet malloc-ot használni, de ez valószínűleg hibás értelmezés volt.