C/C++: Kétdimenziós sztringtömb átadása függvénynek, mit tudok rosszul?
Tudom h a gyakorlatban mutatótömböt vagy dinamikus helyfoglalású tömböt használnak, de szeretném ezt is tudni.
Legyen
char name[ 10 ][ 128 ];
int idx = 0;
A scanf() függvényt szeretném meghívni úgy, hogy a name[idx] -be sztringet olvasson be.
scanf( "%s", name[ idx ] );
Nah ezeket jól értem-e?:
A scanf() függvény argumentumként egy mutatót vár, ahova beírja a beolvasott adatot. A name[ idx ] kifejezést a fordító átalakítja *( name + idx ) kifejezéssé. A kétdimenziós tömb olyan egydimenziós tömb, amelynek minden eleme egy további egydimenziós tömb; továbbá a tömb neve a tömb nulladik elemére mutató pointer. Tehát "name" egy char[] tömbre mutat, az idx hozzáadásával és a dereferálással pedig egy char[] tömb első elemére mutató pointert kapunk és ez a kód jól is működik.
Nézzünk egy másik fvhívást:
scanf( "%s", &name[ idx ] );
Amit a fordító erre z alakra hoz elvileg:
scanf( "%s", &*( name + idx ));
Csakhogy az előzőek alapján a *( name + idx ) eredménye egy mutató, aminek a & operátorral lekérjük a címét, és erre a címre fogja a scanf() az adatot írni, ami viszont értelmetlen, mégis ugyanúgy jól működik a kódom, tehát valamit nem értek jól. Mit?
Megköszönném a segítségeteket,
üdv.
Ja és még egy dolog:
Én a következő hívást részesítem előnyben:
scanf( "%s", name + index );
Ami a dereferálás hiánya miatt eltér a name[idx] -től, mégis úgyanúgy működik. (??)
Na megtaláltam a választ a kérdésemre.
C (C99) szabvány (vagy draft):
6.5.3.2 Address and indirection operators
(3)
"If the operand is the result of a unary * operator,
neither that operator nor the & operator is evaluated and the result is as if both were
omitted, except that the constraints on the operators still apply and the result is not an
lvalue."
83) Thus, &*E is equivalent to E (even if E is a null pointer), and &(E1[E2]) to ((E1)+(E2))
Tehát &name[idx] ugyanaz mint name+idx
Annyit mondhatnátok h nagyjából képben vagyok vagy totál rossz úton járok?
Tévhit hogy a tömbök C-ben pointerek, és ebből szoktak jönni a problémák, főleg multidimenziós tömböknél.
A tömbök az ELSŐ szinten pointerré alakulnak kiértékelésnél, illetve egy függvényben ha paraméterkén lettek átadva, de addig nem. És az után is csak EGY szintig, azaz a char[10][128] nem lesz char** és nem lesz char* sem. Az új típusa char(*)[128] lesz. A fordítónak ismernie kell hogy hány bájt hosszú egy elem a tömbben. De van két kivétel! A sizeof() függvény és a & operátor. Ezek még első szinten se alakítják a tömböt pointerré!
Példa hogy a tömb valóban nem pointer: készíts egy függvényt ami 2 dimenziós tömböt vesz át, és hívd meg a name változóddal:
void func(_____) {
return;
}
int main(void) {
char name[10][128];
func(name);
return 0;
}
Mit kell a func paraméterébe írni hogy elfogadja a fordító?
char name[][128]
vagy
char name[10][128]
Más nem fog működni (a 10 megadható, de nem szokás mert itt már pointer az első szinten, viszont a 128 kötelező).
Ok, most hogy ez tisztázva lett, meg kell említeni hogy mivel a tömb nem pointer, máshogy működnek az operátorok is rajtuk. Tömbön pl. nem értelmezett a ++ operátor, a sizeof() függvény mást ad vissza, és a & is bizony a tömb címét fogja visszaadni és nem a tömb első elemének címének címét. Tömbnek nem lehet értéket átadni, de pointernek lehet.
int alma[4];
Az alma típusa int[], éréke az int[0] elem memóriacíme ami egy int* kiértékelve.
De az &alma értéke az alma tömb memóriacíme, így a típusa int(*)[4]!
Ez ugyan úgy igaz lesz multidimenziós tömböknél is.
A C FAQ-ban a 6-os szekciót olvas el ha nem világos, főleg ezt:
char name[10][128]
A 10 -es helyén mindegy milyen szám van, char(*)[128] lesz a típusa. Bár ha jól értelmezem pontossan erre céloztál azzal, hogy elhagyható mivel nem számít.
C++ standardból egy részlet:
int f(char*);
int f(char[]); // same as f(char*);
int f(char[7]); // same as f(char*);
int f(char[9]); // same as f(char*);
int g(char(*)[10]);
int g(char[5][10]); // same as g(char(*)[10]);
int g(char[7][10]); // same as g(char(*)[10]);
int g(char(*)[20]); // different from g(char(*)[10]);
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!