C-ben mi a tömbre mutató pointer?
Nagyon nem.
Ezt annyiszor félreértik az emberek.
"egy kétdimenziós tömb (int**)"
Nem. A tömb az tömb, a pointer pedig pointer.
Bizonyos kifejezésekben a tömb neve implicit módon első elemre mutató pointerré konvertálódik. A legtöbb kifejezés ilyen, sőt a C szabvány kivételeket sorol fel, amikor ez a konverzió nem történik meg.
int a[5];
a típusa int-ekből álló tömb, ha pl. átadod paraméterként, akkor első elemre mutató pointer adódik át, aminek a típusa int*
int b[5][3];
b típusa kétdimenziós tömb; A b tömbnek 5 eleme van, mindegyik elem egy 3 elemű, int-ekből álló tömb. Ha átadod paraméterként akkor egy első elemre mutató pointer adódik át, ami ez esetben egy 3 elemű, int-ekből álló tömbre mutató pointer, aminek a típusa int(*)[3] // a zárójelek fontosak
82. oldal
6.5.2.1 Array subscripting 4 EXAMPLE
Ennek fényében void foo(int(*)[3]) a szignatúrája egy függvénynek, ami [][3] méretű tömböt fogad. A tömbös jelölésnél hasonlóan az 1. dimenziós mérete elhagyható, a 2. dimenziós mérete nem. void foo(int a[][3])
Mik a kivételek, amikor ez az implicit konverzió nem megy végbe? Például a sizeof() operátor. sizeof(a) az a tömb méretét adja vissza, nem pedig az első elemének mutatójának méretét.
"Szóval ha egy függvényben egy kétdimenziós int tömböt (int**) kell visszaadnod, amelyet a tomb változódban hoztál létre"
Ez teljesen rossz, mert ha a hívóhoz visszajuttatod egy függvény lokális, stack-en létrehozott tömbjének első elemére mutató pointerét, akkor amikorra a hívó megkapja a visszatérési értéket, a függvény lokális változói destruálódtak. Lehet hogy a memóriaterületen még ott vannak a tömb elemei, de a tömb élettartama véget ért, UB.
#6 Ha figyelmesen elolvasod a válaszaimat észreveszed, hogy azzal kezdtem a mondandómat, hogy "C/C++ nyelven a tömb maga az első elemére mutató pointerré redukálódik vissza". Nem fogok 6 oldalas paksamétát írni azért, hogy erre a tényre minden hivatkozáskor felhívjam a figyelmet, sem azért, hogy ennek minden elképzelhető kivételét kifejtsem. A tömb gyakorlatilag egy pointerként kerül kezelésre a legtöbb releváns esetben, ennél nem kell mélyebbre menni.
"Ez teljesen rossz, mert ha a hívóhoz visszajuttatod egy függvény lokális, stack-en létrehozott tömbjének első elemére mutató pointerét, akkor amikorra a hívó megkapja a visszatérési értéket, a függvény lokális változói destruálódtak."
És megmutatnád, hogy hol használtam a stack kifejezést? A kérdező maga írta a kérdésben, hogy malloc-al foglalt helyet a tömbjének, innentől a tömb nem a stack-en jön létre, az egyetlen dolog ami a stack-re kerül az maga a pointerváltozó, annak meg visszaadjuk az értékét a függvény végén.
Harmadszor, a kérdés visszatérési típusokra vonatkozik, és habár kopottas a memóriám a nyelvről, de kétlem hogy return type-nak be tudsz vésni egy olyat, hogy int(*)[3]. Nem, egy kétdimenziós integer tömb visszatérési típusa, hacsak nem akarod nagyon flancosra csinálni, int** lesz. És a kétdimenziós tömb arra fog redukálódni.
Nem értettem én semmit félre, csak a kérdésre igyekeztem válaszolni, és nem egy elnyújtott szemináriumot adni olyasmiről, ami a kérdezőt nem érinti/érdekli.
"Nem fogok 6 oldalas paksamétát írni azért, hogy erre a tényre minden hivatkozáskor felhívjam a figyelmet"
Én is szoktam díjazni azt, amikor vki frappánsan, egyszerűen el tud magyarázni vmit. Ez itt most szubjektív. Véleményem szerint ebben a kérdésben a túlzott egyszerűség miatt az amit leírsz, mást jelent mint amit mondani szeretnél. Ha olyanokat írsz le, hogy "Ha a tomb egy kétdimenziós tömb (int**)" akkor nem meglepő ha félreértik, hiszen a kétdimenziós tömb típusa nem int**.
"És megmutatnád, hogy hol használtam a stack kifejezést? A kérdező maga írta a kérdésben, hogy malloc-al foglalt helyet a tömbjének, innentől a tömb nem a stack-en jön létre"
Ebben teljesen igazad van, bevallom nem olvastam el a kérdés részletezését, ami nem volt korrekt részemről, ezért elnézést kérek, de végigolvasva, meglátásom szerint itt 2 különböző dolog keveredik:
A kérdés: "C-ben mi a tömbre mutató pointer?"
Tömbre mutató pointer egy igazán speciális dolog. A kérdező ezt kérdezte, de mint a részletezésből kiderült, valójában nem erre volt kíváncsi.
A másik dolog, hogy C-ben a malloc/etc által allokált területet inkább nevezik heap/dinamikus tárterület/etc-nek, mintsem "tömbnek". Kapok egy területet, amire azt írok amit akarok, nem is biztos hogy tömbként használom. Attól hogy a tömbindexeléssel is el tudom érni, és nem kell pointer aritmetikában gondolkodni, attól még az nem egy tömb.
"kétlem hogy return type-nak be tudsz vésni egy olyat, hogy int(*)[3]"
ld. a linkelt Stackoverflow kérdés 2. válaszát, de itt egy saját példa:
int (*foo())[3]
{
return malloc(5*3*sizeof(int));
}
Kérdező:
A linkelt Stackoverflow kérdésben az 1. válasz malloc-ol a heapen tárterületet, aminek a kezdő pointerét juttatja vissza a hívóhoz.
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!