• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Sposób ulokowania obiektu w pamięci

Object Storage Arubacloud
+1 głos
179 wizyt
pytanie zadane 2 marca 2018 w C i C++ przez Paweł Dymek Bywalec (2,300 p.)

Witam i grzecznie pytam :)

Mam obiekt ms klasy MS, który ma dużo zmiennych i muszę tam wpisać zmienne z tablicy.

Pisanie kolejno 

ms.godzina=tab[0];
ms.minuta=tab[1];
etc etc

byłoby głupotą, zwłaszcza, że kolejne zmienne są tego samego typu - int.

Jedynym rozsądnym wyjściem jest tu odwołanie się do kolejnych zmiennych w obiekcie ms.

Nie ma czegoś takiego w klasach jak w przypadku verctorów (których NIE MOGĘ użyć i już), że mogę się odnieść do kolejnych zmiennych/obiektów w ten sposób:

ms[0]
ms[1]
itd

Wymyśliłem więc, żeby używać adresu pierwszej zmiennej aby dostać się do poszczególnych zmiennych za pomocą liczby:

#include <iostream>

using namespace std;
class MS
{
	public:
	int var;
	int minn;
	int maxx;
};
int main()
{
    MS ms;
    for(int a=0;a<3;a++)
    {
       *(&ms.var+a)=a+1000;
        cout <<(int)(&ms.var+a)<< "  "<< *(&ms.var+a)<<endl;
    }

    return 0;
}

Pytanie brzmi:

Czy mogę być pewny, że obiekt po utworzeniu zapisywany jest w pamięci w taki sposób, że adresy kolejnych zmiennych zawsze będą ułożone po sobie?

A może jest sposób aby odnieść się do kolejnych elementów obiektu za pomocą liczby, gdzie liczba ta będzie oznaczała numer kolejnego elementu w takiej kolejności jak są zadeklarowane w klasie? Czyli tak jakby to było w przypadku tablicy

ms[0]  to var

ms[1] to minn

itd. Wiadomo, że nie tak jak do tablicy, bo kompilator nie puszcza, ale może jest analogiczny sposób dla klas?

1 odpowiedź

+1 głos
odpowiedź 2 marca 2018 przez Arkadiusz Sikorski Pasjonat (20,160 p.)

Mam obiekt ms klasy MS, który ma dużo zmiennych i muszę tam wpisać zmienne z tablicy.

Jeśli masz dużo (ile to jest "dużo"? 10? 50?) zmiennych składowych i MUSISZ do nich wpisać dużo wartości z tablicy, to prawdopodobnie jest coś nie tak z Twoim pomysłem na tę klasę. 

Wymyślony przez Ciebie sposób po prostu...nie jest dobry. Wyobraź sobie, że musisz wytłumaczyć innemu programiście, jak działa Twój "trick" - stawiam wiele, że na pierwszy rzut oka od razu by się poddał. Lepiej nie polegać na tym, jak poukładane są te zmienne w pamięci, najpierw przemyśl logikę danej klasy (czy nie da się tego jakoś inaczej zaplanować) i w ostatecznej ostateczności kombinuj z takimi nietuzinkowymi rozwiązaniami.

Zacznijmy od tego:

  • co ma robić ta klasa?
  • co oznacza "dużo zmiennych"?
  • co te zmienne trzymają?
  • dlaczego musisz przepisać te zmienne z tablicy?
komentarz 2 marca 2018 przez Paweł Dymek Bywalec (2,300 p.)
edycja 2 marca 2018 przez Paweł Dymek

Napisałem z tablicy, bo to to samo, a nie chciało mi się tego tłumaczyć obszernie, ale skoro dopytujesz to może podsunie Ci to jakieś rozwiązanie.

A więc tak, urządzenie na którym będzie ten program posiada tylko jedno wejscie - encoder. Encoder posiada 3 'przyciski' tj kręcenie w lewo, w prawo i kliknięcie. To co chcę zrobić to obsługa ustawień za jego pomocą. Wchodzę w menu, wybieram daną opcję(tym się nie martw, to już zrobione) i teraz zaczyna się obsługa ustawień:

Wyświetlam liczbę, kręcę sobie aby ją zwiększyć/zmniejszyc, a jak kliknę to chcę ją zapisać do ms.var i przejść do kolejnej liczby. Na wyswietlaczu ciągle jest wyswietlana liczba, ktora ustawiam, ale po kliknieciu wyswietlam juz kolejna zmienna czyli ms.minn. Kręcę znowu i po kliknieciu ma się ustawiona wartosc zapisac do ms.minn itd itd

Ile zmiennych? to się okaże po ukończeniu programu, dlatego nie chcę pisać w obsłudze czegoś na wzór

if(a==0)
{
    ms.var=to_co_ustawione;
}
else if(a==1)
{
    ms.minn=to_co_ustawione;
} itd itd

bo to tak jak pisałem wyglada tragicznie, a zmiennych moze bedzie 20 a moze 100 a moze w przyszlosci dojdzie wiecej ...

Tak jak pisałem wszystkie typu int.

Struktura klasy w ten sposob zorganizowana jest czytelna i poprawna. Gdyby zrobił tablicę intów o rozmiarze np 100 to musialbym pozniej pamietac ktory jest od czego lub zrobić enuma do niej, w gruncie rzeczy musiałbym i tak wypisać wszystko po kolei, ale kod byłby brzydki po takich operacjach. W innym miejscu w kodzie muszę się precyzyjnie odnosić do poszczególnych elementów obiektu tej klasy więc używanie nazw zamiast numerów tablicy jest o niebo wygodniejsze.

Mógłbym też utworzyć tablicę wskaźników na wszystkie te elementy lub funkcję wew te klasy, która by ustawiala konkretna wartosc na podstawie podanego numeru, ale tu znowu musze wypisac wszsytko recznie. Nie robi mi roznicy czy zrobie to w kodzie czy wew klasy (chociaz druga opcja podniesie czytelnosc kodu).

 Najprosciej byloby wlasnie odwolywac sie jakos do poszczegolnych elementow podajac jedynie numer tego elementu, ale nie wiem jak to zrobic. Tzn niby ten sposob co podalem dziala na testowym programie, ale czy moge byc pewny, że zawsze obiekt zapisywany jest w taki sposob w pamieci?

komentarz 2 marca 2018 przez Arkadiusz Sikorski Pasjonat (20,160 p.)
edycja 2 marca 2018 przez Arkadiusz Sikorski

Jeżeli to będzie POD, to powinno być ułożone w dokładnie tej kolejności. Kolejność może być różne, jeżeli używałbyś np. i public i private. 

struct MS{
	private:
		int a;
		int b;
	public:
		int c;
		int d;
}

w powyższym przypadku nie wiadomo, czy najpierw będzie a czy c, ale wiadomo, że b będzie po a oraż d po c. Czyli możliwe warianty: abcd albo cdab.

Gdyby zrobił tablicę intów o rozmiarze np 100 to musialbym pozniej pamietac ktory jest od czego lub zrobić enuma do niej

Akurat w typ przypadku enum nie byłby takim złym pomysłem. Popatrz na to:

#include <iostream>
struct MS
{
	enum // tak jakbys deklarowal zmienne w klasie
	{
		varMin, // = 0
		varMax, // = 1
		whateverMin, // = 2
		whateverMax, // = 3
		// itd.
		maxEnumerator // = 4, dzieki temu wiemy, ile pol mamy
	};
	int data[maxEnumerator]; // nasz enumerator policzył za nas, ile mamy pól w klasie; to samo co int data[4];
	int& operator[](int index) {return data[index];} // to dla wygody
};


int main()
{
	MS ms;
	ms.data[MS::varMin] = 11;
	ms[MS::whateverMin] = 22;
	std::cout << sizeof(MS);
	return 0;
}

Oczywiście enuma możesz zadeklarować poza MS, wtedy nie będziesz musiał używać operatora zakresu MS::. "Sztuczka" użyta powyżej jest dużo czytelniejsza i jest kompromisem pomiędzy zwięzłym i czytelnym zapisem. 

Zabawy z kolejnością pól i wyrównaniem (paddingiem) pól w strukturze mogą być niebezpieczne, bo wyrównanie może być zależne od implementacji. Jeśli jesteś pewien, jak to działa na Twojej platformie, możesz skrócić zapis do czegoś takiego:

for(int a=0;a<3;a++) // zauwaz, ze tutaj musisz pamietac/znac ilosc pol w klasie
   (&ms.var)[a] = a + 1000;

 

Podobne pytania

0 głosów
0 odpowiedzi 228 wizyt
pytanie zadane 27 lutego 2018 w Mikrokontrolery przez Paweł Dymek Bywalec (2,300 p.)
0 głosów
3 odpowiedzi 393 wizyt
+2 głosów
1 odpowiedź 1,287 wizyt
pytanie zadane 1 listopada 2016 w C i C++ przez Arturo332 Początkujący (250 p.)

92,575 zapytań

141,424 odpowiedzi

319,649 komentarzy

61,960 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...