Wlasna implementacja sizeof()

0

Witam!
Zwracam sie z prosba o pomoc w sprawie napisania w C++ funkcji zwracajacej rozmiar typu danych zmiennej podanej jako argument. Taki wlasny sizeof(). Nie chodzi mi o jakiegos gotowca czy cos podobnego.

Interesowaloby mnie raczej to, w jaki sposob mam sie do tego zabrac (co wykorzystac itd.) i ogolnie jak by to mialo wygladac. Wczesniej nie zajmowalem sie funkcjami tego typu, raczej tylko algorytmika.

0

Efektywnie najprościej użyć wskaźników - efektem powiększenia wskaźnika na konkretny typ jest przesunięcie go o rozmiar danego typu, z tego zaś wynika, że powiększenie adresu zerowego da sam rozmiar:

#include <cstddef>
// ...

template <typename Type>
size_t fsizeof(const Type &) {
    return (size_t)(((Type *)0) + 1);
}
0

No fajowo, dziala :P
Tylko chcialbym jakies sensowniejsze wyjasnienie do tego, ze wskaznikow za wiele nie umiem...

0

Też bym poprosił o wyjaśnienie.
W szczególności:
((Type *)0)

0

Wskaźnik służy do przechowywania adresu w pamięci, wskazywania na ten adres, ew. leżący tam obiekt. Siłą rzeczy różnice pomiędzy adresami kolejnych obiektów muszą być równe ich rozmiarowi. Więc załóżmy, że mamy pod adresem 0 tablicę obiektów, ten pod indeksem 0 będzie miał adres 0, następny natomiast będzie mieć adres równy rozmiarowi typu, adres kolejnego już 2*sizeof(typ). Używając indeksowania można wcześniejszą funkcję zapisać jaśniej:

template <typename Type>
size_t fsizeof(const Type &) {
        return (size_t)&((Type *)0)[1];
/* 
        lub wręcz:

        Type *wirtualnaTablica = 0;
        return (size_t)&wirtualnaTablica[1];
*/
}

@pcmcymc (niżej), nie, chodzi tylko o różnicę potencjalnych adresów obiektów, nie same obiekty. Wskaźnik jest tylko wartością opisującą adres.

0

Nie musisz utworzyć tych elementów poprzez new?

0

to ja się nieładnie wtrącę w temat i wyjaśnię.

jak wiemy, wskaźnik przechowuje początek adresu, od którego opisana jest pewna dana.

Żeby poznać rozmiar danej w pamięci, możemy sobie stworzyć wskaźnik, który zakłada, że w pewnym miejscu jest ta dana, nie interesuje nas co tam jest, liczy się to, żeby kompilator wierzył, że tam jest coś takiego.

Następnie potraktujmy ten wskaźnik jako nazwę tablicy, tj. jeśli masz np. int tab[10], to jeśli napiszesz w programie tab, to inaczej, jakbyś napisał &tab[0] (& - ampersand to operator pozwalający poznać adres pamięci, w której przechowywana jest zmienna),
jeśli do wskaźnika ((Type *)0) dodamy jeden, tj. przejdziemy na kolejny element w tej naszej pseudo tablicy (należy pamiętać, że to, co robimy, to inkrementowanie wskaźnika, nie jego wartość zmiennej, na która wskazuje).

Kiedy znamy adres początku ciągu bitów opisujących zmienną, która byłaby druga z kolei w tablicy, której początek też znamy (tj. 0), to różnica adresów, na które wskazują te wskaźniki to to, czego szukamy.

0

Juz w miare rozumiem.
Moglby tylko ktos jeszcze wyjasnic roznice pomiedzy wskaznikiem a ampersandem, skoro oba w jakis sposob wskazuja na adres?

0

Ja wiem że to to samo, ale jak już chcemy zerowy wskaźnik, to lepiej użyć NULL a nie 0.

0

@tomciokotar, wskaźnik (jako zmienna) przechowuje adres, operator pobrania adresu (ampersand) zwraca adres tego co stoi po jego prawej stronie.

@Azarien, w sumie fakt. I tak użycie size_t, tak jak i NULL, wymaga włączania włączenia cstddef. Akurat z 'bez-nullowym' kodem pracowałem, leci poprawka.

// edit, albo i nie, akurat tutaj ze względów 'dydaktycznych' użycie zera wprost nie jest złym pomysłem, jasno określa zerowy adres, nie pusty wskaźnik.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0