Tömb mérete miért marad 4?
Üdv!
Tömbökkel, pointerekkel, malloc, calloc, realloc függvényekkel kísérletezek. Egy olyan programot szeretnék írni, ami növelgeti egy tömb számára lefoglalt memóriát, és a felszabadult helyre egy számot rak. Ez eddig kész is van, de arra gondoltam, jó lenne annyival tovább bonyolítani, hogy a tömb mérete ne növekedjen minden ciklusban, hanem csak akkor, ha megtelik (ekkor több, mint egy sizeof(int) területet lefoglal), és ezt a tömb elemszámán keresztül lehetne ellenőrizni. Sajnos bármekkora memóriát foglalok le, és akárhány elemet rakok a tömbbe, a sizeof() eredménye mindig négy. Gondolom azért, mert a tömb neve az első elemére mutató pointer. De akkor honnan tudjam meg, hány elemmel van éppen feltöltve a tömböm?
Itt az utolsó működőképes részlet, bár nem kell, hogy megírjátok helyettem, csak valami ötlet kellene az *x méretének meghatározására:
Ha jól sejtem, C.
A tömb méretét kénytelen leszel magad nyilvántartani, mivel csak egy pointered van, a compiler pedig ebből nem fogja tudni, hogy az mekkora területre mutat majd runtime.
Egyébként az általad leírtak mentén működik a Java ArrayList típusa is.
struct dynamic_array {
int *data;
size_t size;
size_t allocated;
};
Mondjuk jelentse a size azt, hogy éppen mennyi van benne, az allocated meg azt, hogy éppen mekkora.
Szerintem kész, már csak írni kell hozzá függvényeket.
Az a furcsa, hogy ha olyat csinálok, hogy:
int x[5] = {1,2,3,4,5}
akkor sizeof(x) == 20, ami ugye 5*sizeof(int)-nek felel meg. Azt vártam, hogy pointeres tömbnél is le lehet így kérdezni elemek számát. Nem világos számomra, hogy mi a különbség a kettő között.
A statikus tömb (int a[] = {1, 2, 3};) elemszámát (sizeof(a)/sizeof(a[0]) azért tudod lekérdezni, mert az fordításkor értékelődik ki.
Amennyiben dinamikus tömböket használsz, kénytelen vagy számon tartani a tömböd méretét, mivel máshogyan nem tudod lekérdezni az elemszámot.
Nem teljesen pontos amit uno20001 írt. Azért kapsz 4-et mert nem tömbnek hanem pointernek deklaráltad a változód, aminek a mérete 4 bájt 32 biten, 8 bájt 64 biten.
A sizeof() függvény különbséget tesz pointer és tömb között, kivéve ha a tömb egy függvény deklarációjában van, mert akkor automatikusan helyettesíti a fordító azt egy pointerrel. Sajnos pointerből viszont nem lehet tömb típust csinálni, csak a tömb szintaktikáját használni, tömböt imitálva ezzel.
A sizeof() valóban, általában fordításkor értékelődik ki, de nem mindig ez a helyzet. C99-től a tömb méretét nem csak konstanssal de változóval is meg lehet adni, az így deklarált tömböket a program számon tartja és a sizeof() mindig futás időben értékeli ki a méretüket.
Erre példát is ad a C standard dokumentációja:
#include <stddef.h>
size_t fsize3(int n)
{
char b[n+3]; //variable length array
return sizeof b; //execution time sizeof
}
int main()
{
size_t size;
size = fsize3(10); // fsize3 returns 13
return 0;
}
Ha lekérdezed egy tömb típusát, meg tudod nézni minek tekinti a fordító:
int foo[5]; //foo típusa: int[5]
void bar(int foo[5]) {} //foo típusa: int *
int bar 5; int foo[bar]; //foo típusa: int[(sizetype)(bar)]
A típustól függ hogy mit fog visszaadni a sizeof().
Fun fact: pár kivételes esettől eltekintve (pl sizeof), a fordító a tömböket pointerekké konvertálja h az nem a kifejezés bal oldalán áll, ezért ezek mindegyik helyes és egyenértékű egy kifejezés jobb oldalán: tomb[5], *(tomb+5), *(5+tomb), 5[tomb]
Szintaktikai hibák:
int tomb[5];
tomb++; /*nem értelmezhető*/
tomb=tomb+1; /*nem lehet (int *)-t tomb[5]-é konvertálni*/
int* tomb2=tomb; /*helyes tomb[5]-t lehet (int *)-é konvertálni*/
tomb2++; /*helyes*/
int bar=tomb2[2]; /*helyes*/
void foo(int tomb[]) {tomb++;} /*helyes mert függvény deklarációban automatikusan pointer lesz belőle*/
A *alloc függvények pointereket adnak vissza, ezek nem tömbök, csak mutatók amik egy lefoglalt területre mutatnak, ezért a sizeof() a mutató méretét fogja visszaadni és nem a lefoglalt terület méretét. Mutatót nem lehet tömbbé alakítani, ezért neked kell számon tartanod egy változóban azt, hogy mennyit foglaltál le.
Valójában a lefoglalt terület méretét számon tartja a program, amihez egyébként hozzá is lehet férni, de ez nincs specifikálva, és platform és fordító függő. Nem véletlenül tudja a free() parancs mennyit kell felszabadítania.
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!