Sziasztok,
Azt gondoltam ez mukodik:
#include <stdlib.h>
#include <string.h>
void stralloc(char *str)
{
str = malloc(10);
strcpy(str, "Hello");
}
int main(void)
{
char *str;
stralloc(str);
return 0;
}
..de nem. Viszont hogy lehet?
/sza2
Szerk.: Megoldva (es talan mar ertem is:-)
- 5419 megtekintés
Hozzászólások
passed by value
.. (char **str) { *str = malloc(10); strcpy(*str, .. stralloc(&str); ..
- A hozzászóláshoz be kell jelentkezni
Szerintem a fenti pelda cim szerinti atdas. Vagy nem?
/sza2
- A hozzászóláshoz be kell jelentkezni
Akkor olvasd el az adott peldat, meg a te kododat, es lasd a kulonbseget. A te kodod ertek szerinti atadas - tekitnve, hogy ez a default a C-ben.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal
- A hozzászóláshoz be kell jelentkezni
De akkor a
char array[10];
func(array);
ezek szerint nem cim szerinti atadas?
/sza2
- A hozzászóláshoz be kell jelentkezni
ezek szerint nem cim szerinti atadas?
de.
a tömb tartalmának cím szerinti átadása (= mind a 10 byte)
ennek előfeltétele, hogy a tömb címe már létezzen.
de te nem a tömb tartalmát, hanem a címét szeretted volna cím szerint átadni. ahhoz kell a char **
- A hozzászóláshoz be kell jelentkezni
Ertem, amit irsz, csak azt nem ertem, miert van igy. Az en agyamban ez van:
Adott egy valtozo, ami jelen esetben legyen *x, egy pointer. Merete mondjuk 32bites cimzes eseten 4byte. Ha azt mondom, *x = NULL akkor arra (azokra) a cim(ek)re ahol ez a valtozo van (tegyuk fel 0x00001234-0x00001237), beirodik 0x00000000, es mostantol ez lesz az x pointer.
Azutan a malloc()-kal foglalunk egy keves memoriat, a visszateresi erteke pedig szinten egy 32bites ertek, az a cim, ahol jo esetben talaltunk eleg egybefuggo memoriat, legyen 0x12345678.
Amikor azt mondom, x = malloc(N), ez az ertek felulirja a 0x00001234-0x00001237 cimeken levo erteket. Innentol kezdve, a x azt mondja meg, hol kezdodik a memoria terulet, ahova irhatok.
Azt nem ertem, miert kell ehhez a fuggveny hivasa elott tudni, hogy hol a szabad teruletem?
/sza2
- A hozzászóláshoz be kell jelentkezni
Programozo szabaly #1: Az, hogy a te agyadban mi van, tokmindegy. A gep azt csinalja, amira utasitottad, nem azt, amire gondoltal.
Nagyjabol ugy van, ahogy leirtad, de javaslom, azert fusd at a C konyv vonatkozo reszeit ujra, hogy a szakzsargonnal tisztaban legyel.
Amiben hibadzol, az az, hogy fuggvenyhivas is van a kepben. A pointer, mint valtozo, ertek szerint adodik at (hogy mire mutat, az itt most mellekes - a pointer, mint valtozo maga ertek szerint adodik at. Ezert amikor a malloc() visszateresi erteket beleirod a valtozoba, az ott, a fuggvenyen belul megkapja az erteket, de amikor visszater a fuggveny, felszabadul a stack (mivel parameterek es helyi valtozok a stack-en kapnak helyet), es a hivasi helyen ujra a korabbi erteket kapja.
Ez most igy bonyi, de olvass utana, hogy muxik.
- A hozzászóláshoz be kell jelentkezni
+1, csak kiegészítésnek:
@sza2king:
valszeg az zavar meg, hogy a függvénynek átadod a main-ben lévő lokális pointered értékét, ez a stack-en jön létre, majd ezt felülírod a függvényen belül a malloc-tól visszakapott értékkel, még mindig a stack-en. majd ahogy írták, ez visszatérés után felszabadul.
tehát ahogy már többen leírták, a pointer címének (mint érték) a címét kell átadnod, így ez a main lokális változójának memória részére fog mutatni, és ezt a malloc által visszaadott értékkel felülírhatod, ilyenkor már valóban az eredeti main lokális változójának a memória részébe írod vissza.
ami itt zavaró lehet, hogy a pointerek értéke is egy cím, mely további memória rész értékére mutathat.
megj.: motorolán lehetett assembly-ben jó kis indirekt címzéseket csinálni (ha jól rémlik, 68020 és attól felfelé volt bonyolultabb extra címzés mód is), na ott is volt olyan, hogy meg kellett állni tanárúr egy kicsit elgondolkodni :)
- A hozzászóláshoz be kell jelentkezni
"Az, hogy a te agyadban mi van, tokmindegy. A gep azt csinalja, amira utasitottad, nem azt, amire gondoltal."
Ok, ez azert meg megvan :-) BTW, azert iram ide, hogy korrigalodjon az elkepzelesem, hiszen nem ugy volt ahogy en gondoltam, es ezt a program is bizonyitotta...
Mostmar viszont megertettem (legalabbis azt hiszem:-), s bar emlekeztem ra, hogy a lokalis valtozok a stack-en keresztul adodnak at, szukseg volt a magyarazatokra, amit koszonok is mindenkinek.
Annyira nem is bonyolult, csak vegig kellett gondolni.
Ja, raadasul mukodik is:-)
/sza2
- A hozzászóláshoz be kell jelentkezni
c-ben nincs cim szerinti atadas, csak ertek szerinti
--
NetBSD - Simplicity is prerequisite for reliability
- A hozzászóláshoz be kell jelentkezni
Nem vagyok egy C guru, nagyreszt autodidakta modon tanultam meg.
Viszont akkor a
int x;
func(&x);
kodreszletben az x nem cim szerint adodik at?
/sza2
- A hozzászóláshoz be kell jelentkezni
gyakorlatilag igen, de facto nem: az x címe adódik át érték szerint. ami pont ugyanolyan jó, mintha az x-et adnánk át cím szerint. a lényeges különbség, hogy a func függvényben nem az 'x' lesz a paramétered, hanem 'x címe', és eszerint is kell majd ott használnod.
- A hozzászóláshoz be kell jelentkezni
Ez a "gyakorlatilag igen, de facto nem", eleg erdekes kifejezes:-)
/sza2
- A hozzászóláshoz be kell jelentkezni
mutató típusú változó, vagy hogyisvanez.
--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.
- A hozzászóláshoz be kell jelentkezni
nem, hanem a cime adodik at ertek szerint :)
ezt fusd at, hogy megertsd miert igy van:
http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl
--
NetBSD - Simplicity is prerequisite for reliability
- A hozzászóláshoz be kell jelentkezni
Miért nem jó neked az strdup?
- A hozzászóláshoz be kell jelentkezni
Tudtommal az ISO C könyvtárnak nem része a strdup.
- A hozzászóláshoz be kell jelentkezni
Úristen
- A hozzászóláshoz be kell jelentkezni
http://en.wikipedia.org/wiki/String.h
Extensions to ISO C
char *strdup(const char *src); allocates and duplicates a string into memory POSIX; originally a BSD extension
- A hozzászóláshoz be kell jelentkezni
és?
- A hozzászóláshoz be kell jelentkezni
Úristen
- A hozzászóláshoz be kell jelentkezni
Roppant kreatív vagy. Elfelejtettem, hogy gondolatolvasó is vagy, mert én azóta sem látom, hogy hol írta a kérdező, hogy neki ISO C kell.
- A hozzászóláshoz be kell jelentkezni
Sot, meg azt sem irta, hogy strdup kell - vagyis inkabb pont nem strdup kell :-) Leginkabb egy strdup-ot (valami hasonlot) akart irni.
/sza2
- A hozzászóláshoz be kell jelentkezni
Tulajdonkeppen pont egy strdup szeruseget kellene megvalositani. Eloszor a fuggveny neve is str_dup() volt, csak atirtam, nehogy valaki arra asszocialjon. Nem jott ossze:-)
/sza2
- A hozzászóláshoz be kell jelentkezni
szerintem meg ez működik.
igaz, nem csinál semmit, de végülis azt se értem, hogy mit szerettél volna...
- A hozzászóláshoz be kell jelentkezni
Igazi fejlesztői hozzáállás :)
- A hozzászóláshoz be kell jelentkezni
Na ja működik a függvényen belül, csak éppen nem tudja ezen a módon visszadani a pointert. Mert az átadott változó pont úgy müködik, mint egy blokkra lokális dinamikus változó. Ha a kérdéses értéket (ebben az esetben az inicializált pointert) a paraméter szignatúrán keresztül akarod visszadani, akkor annak a címét add át, tehát a pointer címét.
Aztán a függvény belsejében mehet az indirekció.
Röviden ennyi.
- A hozzászóláshoz be kell jelentkezni
Vegulis, igy az sem igaz, hogy nem csinal semmit, hiszen a kod vegrehajtodik (ha mar nyelveszkedunk).
Azt szerettem volna, ha a fuggvenyen kivuli pointer-em a fuggvenyen belul allokalt memoriara mutatna, azutan is, hogy a fuggveny befejezodott.
/sza2
- A hozzászóláshoz be kell jelentkezni
igy az sem igaz, hogy nem csinal semmit, hiszen a kod vegrehajtodik
a fenti kódban teljesen mindegy, hogy a függvényből visszakerül-e a lefoglalt pointer a mainbe vagy sem, mivel a main se használja semmire se. tök mindegy, hogy melyik függvény dobja el.
egyébként erre találták ki alapvetően a visszatérési értéket.
char *stralloc()
{
char *str = malloc(10);
if (str != NULL) strcpy(str, "hello");
return str;
}
elvileg lehet úgy is, ahogy mások mutatták (pointer a pointerre átadásával), de ha nem muszáj (= lehet máshogy is), akkor azt inkább nem használjuk.
- A hozzászóláshoz be kell jelentkezni
"main se használja semmire se"
Ez leginkabb azert lehet, mert nem akartam idemasolni az egesz programot, csak egy zanzasitott valtozatott, arrol a reszrol amit nem ertettem.
"main se használja semmire se"
Lasd fentebb. Van visszateresi ertek, csak mar foglalt masra.
Szoval a fenti program, csak a problemam bemutatasara szuletett, nem igy, ebben a formaban szerettem volna hasznalni:-)
/sza2
BTW, ezt a mulattsagot tombok tombjevel kellene eljatszanom, csak egyszerusitettem egy kicsit. Szoval a vegen majd valami int fuggveny(char *a, char* b, char ***c, int d, int e) lesz belole, csak a char *** mar eleg undorito...
- A hozzászóláshoz be kell jelentkezni
Tobbdimenzios tomb atadasa picit trukkos, a *** nem lesz jo.
- A hozzászóláshoz be kell jelentkezni
Ennek semmi koze a C++-hoz. Siman jo a ***, ha tudod, mit csinalsz. Ez csak egy magasabb foku cimzes. Nyilvan csak ugy van ertelme, ha 3 masik parameterben atadod az egyes indexek ertelmezesi tartomanyat. Amugy ennel sokkal szebb megoldas a sima egyszeres pointer, es dope vector hasznalata.
- A hozzászóláshoz be kell jelentkezni
A mellekelt peldanak sincs koze a C++-hoz, kar volt azon leragadni. A *** pedig azert nem jo, mert atadaskor elveszik a sormeret, ergo nem fogod tudni tobbdimenzios tombkent hasznalni; mig ha a tombos modon adod at, akkor ez az informacio megmarad. Roviden: nem olvastad el.
- A hozzászóláshoz be kell jelentkezni
Lenyeg a lenyeg, amit akartam haromcsillagos megoldas lett, es mukodik. A valodi programban valtozo hosszusagu, de 0 terminalt szovegek tombjere van szuksegem, es ezen szovegek darabszama dinamikusan valtozik (egy *argv[] szeru tomb a kimenete a fuggvenyemnek). A sztringek hossza adott a 0 lezaras miatt, azt pedig, hogy hany darab, szamolom.
/sza2
- A hozzászóláshoz be kell jelentkezni
Ha tombos modon adod at, akkor a stackbe belekerul a memoriaterulet hossza, ugyanugy, mintha dope vectort vagy eppen plusz parameterkent az egyes tombdimenziok ertelmezesi tartomanyat adnad meg. Az, hogy a compiler ezt neked igy talalja, attol meg ugyanugy at KELL adni az informaciot, csak az egyik esetben nyelvi elem az informacioatadas, a masik esetben meg neked kell gondoskodnod rola.
Magyaran: a tombos modon valo adatas ugyanaz, mintha melleirnad egy valtozoban a sormeretet. Ugyanaz a kod fog generalodni. Remelem erted, miert ugyanaz a ket dolog. Amit mindig szem elott kell tartani C programozasnal: nem mas ez, mint egy portable assembly, alacsonyszintu minden, a nyelv nem sok midnent rejt el eloled a gep kepessegeibol.
- A hozzászóláshoz be kell jelentkezni
Ertem, csak azt nem, hogy ha ugyanaz a ketto, akkor miert akarsz vele szopni kulon? :)
- A hozzászóláshoz be kell jelentkezni
Azert, mert a te konstrukciod csak forditasi idoben ismert meretu matrixoknal jo, viszont a leggyakoribb esetben a forditasi idoben a meret nem ismert, csak futasi idoben lesz az.
- A hozzászóláshoz be kell jelentkezni
"a tombos modon valo adatas ugyanaz, mintha melleirnad egy valtozoban a sormeretet. Ugyanaz a kod fog generalodni. "
nem.
Vagy irjal pelda kodot, ami ugyan azt adja.
Amit nem lehet megirni assemblyben, azt nem lehet megirni.
- A hozzászóláshoz be kell jelentkezni
"egyébként erre találták ki alapvetően a visszatérési értéket."
Igen is, meg nem is. Pl. adott egy bonyolultabb struktura, amit fel kell inicializalni, mondjuk tobbek kozt fajlbol (ez egy egyszerubb eset). Ket dolgot kell jelezned a hivo fele: az inicializalas sikerult/nem sikerult, illetve a konkret strukturat.
C-nel altalaban az a megoldas, hogy egy int mystruct_init(struct mystruct*) vagy egy int mystruct_init(struct mystruct**) szignaturaju fuggvennyel toltjuk fel a strukturat, az int visszateresi ertek pedig egy statuskod (jobb esetben 0/1), ami jelzi az inicializalas sikeresseget.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal
- A hozzászóláshoz be kell jelentkezni
+1
--
NetBSD - Simplicity is prerequisite for reliability
- A hozzászóláshoz be kell jelentkezni
Pointer visszatérési értéknél NULL jelezhet hiba kondíciót simán. Aminek már több értelme van az az, ha minden fgv hibakódot ad vissza, és nem csak 0 / 1, hanem pl. egy enum-ból választja ki a hibakódokat.
Üdv,
Gergely
- A hozzászóláshoz be kell jelentkezni
Jelezhet, de nem biztos, hogy ez a tokeletes megoldas. Ugyanis a 0/1 es a pointer NULL/nem NULL ertek mar eleve 4 fele hibajelzesre ad lehetoseget, mig siman csak a pointer vizsgalata 2 fele hibajelzest foglal magaban.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal
- A hozzászóláshoz be kell jelentkezni
> ha minden fgv hibakódot ad vissza, és nem csak 0 / 1, hanem pl. egy enum-ból választja ki a hibakódokat.
Szerintem egy függvény elég ha jelzi a hibát (NULL, 0, '\0', -1, vagy más értéktartományon kívüli elem visszaadásával), a hibakód meg kiderülhet az errno -ból.
- A hozzászóláshoz be kell jelentkezni
Tobbszalu alkalmazasnal ez erosen ellenjavalt, siman felulirhatjak egymas hibajelzeseit.
- A hozzászóláshoz be kell jelentkezni
> Tobbszalu alkalmazasnal ez erosen ellenjavalt, siman felulirhatjak egymas hibajelzeseit.
# if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value. */
# define errno (*__errno_location ())
# endif
- A hozzászóláshoz be kell jelentkezni
Es ha van harom szalam (egy master es ket worker), akkor a master hogyan latja a worker altal eloallitott hibakat, hogy ha az errno szalankent ertelmezett? Egy szal egy masik szal altal irt errno-t hogyan latja?
- A hozzászóláshoz be kell jelentkezni
> a master hogyan latja a worker altal eloallitott hibakat
Általánosságban: a master átad egy feladatot egy worker-nek, az meg visszaadja a feladatot, kiegészítve a feldolgozás eredményeivel. A szálak nem olvasgatják egymás errno-ját, mert csak az adott szál tudja helyesen értelmezni az értékét.
- A hozzászóláshoz be kell jelentkezni
Ezt en sem ertem... mintha ez lett volna a felvetesed: "a hibakód meg kiderülhet az errno -ból.", viszont most meg azt mondod, hogy nem olvasgatjuk az errno-t. Akkor a master honnet fogja tudni a hiba okat? No offense, tenyleg nem vilagos nekem.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal
- A hozzászóláshoz be kell jelentkezni
Ugy, hogy a gyerek nezi meg az errno-t miuan lata, hogy valami baj van.
A szulo meg ugyan ugy ertesul, mint barmi masrol, mint pl. eredmeny -rol.
Amit nem lehet megirni assemblyben, azt nem lehet megirni.
- A hozzászóláshoz be kell jelentkezni
Akkor pont ugyanoda lyukadunk ki, mint a szalindito: az eredmeny jelzese egyben errno is. Azaz megint ujra fel KELL talalni a melegvizet.
- A hozzászóláshoz be kell jelentkezni
> az eredmeny jelzese egyben errno is
Nem tudom mit értesz "eredmény jelzése" alatt, de csak az errno az, ami errno. Az "eredmény jelzése", az nem errno.
- A hozzászóláshoz be kell jelentkezni
+1
- A hozzászóláshoz be kell jelentkezni
> void stralloc(char *str)
void stralloc(char **str)
*str = malloc(10);
...
char *str;
stralloc(&str);
Vagy valami ilyesmi.
- A hozzászóláshoz be kell jelentkezni
Igen ez a jó megoldás.
- A hozzászóláshoz be kell jelentkezni
(leirtak fentebb)
- A hozzászóláshoz be kell jelentkezni
void stralloc(char **strptr)
{
*strptr = malloc(10);
strcpy(*strptr, "Hello");
}
int main(void)
{
char *str;
stralloc(&str);
printf("%s\n", str);
return 0;
}
Ez nagyjából jónak tűnik.
Hozzáteszem fogalmam sincs a C programozásról, sajnos :(
- A hozzászóláshoz be kell jelentkezni
+1, ez így helyes:)
- A hozzászóláshoz be kell jelentkezni
Igazabol ez szimpla ertek atadas tovabbra is, a pointer is ertek (memoriacim egesz pontosan). Ha jol szeretned megvalositani, akkor egy pointer kell, ami a pointeredre mutat:)
- A hozzászóláshoz be kell jelentkezni
Igen, errol szolnak a valasz-peldak is:-)
/sza2
- A hozzászóláshoz be kell jelentkezni
jajam, csak nem láttam sehol sem megmagyarázva a miértet, gondoltam leírom az utókornak:)
Rengeteg alkalommal futok bele olyan fórumokba, ahol a kérdést feltették, majd leírták hogy "megoldottam", csak a hogyan/miért nincs odaírva.
(közben fentebb látom valaki kicsit obfuszkáltabban, de leírta:))
- A hozzászóláshoz be kell jelentkezni