Dynamiczna tablica obiektów- problem(wyswietla śmieci)

Dynamiczna tablica obiektów- problem(wyswietla śmieci)
marcinmierzejewski1024
  • Rejestracja:prawie 13 lat
  • Ostatnio:ponad 2 lata
  • Postów:14
0

kod:

Kopiuj
//dynamiczna tablica na obiekty
void create(test *wskaznik,int ile)
	{
	wskaznik=(test *)malloc(ile*sizeof(test));
	int i=0;
	for(i=0;i<ile;i++)
		{
		cout<<i<<" liczba \n";
		wskaznik[i].liczba=i;//bo obiekt
		}
	}

void get(test * wskazn,int liczba)//wyswietlanie
	{
	for(int i=0;i<liczba;i++)
		{
		cout<<wskazn[i].liczba;
		}
	}
void destroy(test *wk,int ile)//zupelnie niepotrzebny 2 argument ale mialo byc przeciązenie wiec jest
	{
	free(wk);
	}


użycie:

Kopiuj
test *wsk2=(test*)malloc(sizeof(test));//dalem ponieważ bez tego wywalalo blad że niezainicjowana zmienna
create(wsk2,5);
get(wsk2,5);
destroy(wsk2,1);

niestety zamiast liczb 0,1,2,3,4 wyswietla śmieci z pamieci. Mi sie wydaje że wszystko w porzadku, kompilatorowi też.
Widzicie może co robie źle?

RR
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 12 lat
  • Postów:6
1

Wydaje mi się że problem jest wsk2. Robisz malloca, potem wywołujesz create który znowu (!) robi malloca i dopiero teraz czyni jakieś czary na tej pamięci. I teraz zagadka get dostaje wsk2 do której pamięci? Tej pierwszej czy tej zalokowanej w create? :)

marcinmierzejewski1024
a sprawdziłem debuggerem faktycznie dostał adres z tego pierwszego malloca..
Endrju
  • Rejestracja:około 22 lata
  • Ostatnio:prawie 2 lata
1

Przede wszystkim wskaźnik możesz po prostu zainicjalizować wartością NULL. Po drugie to, że przekazujesz wskaźnik nie oznacza, że możesz zmieniać adres na jaki wskazuje. A to właśnie próbujesz zrobić wewnątrz funkcji create - przypisujesz adres zwrócony przez malloc. Ale nie zmieni to adresu, na jaki wskazuje wsk2 (zmieni się wskaznik wewnątrz funkcji) a wskazuje on na jakieś śmieci.

Jeżeli chcesz alokować wewnątrz funkcji - zwróć ten wskaźnik.

Ładnie to widać, jeżeli użyjesz sobie typedef:

Kopiuj
typedef int * int_ptr_t;

Jeżeli teraz napiszesz taką funkcję:

Kopiuj
void funkcja(int_ptr_t wskaznik) {
  wskaznik = jakas_tam_wartosc;
}

To sam przyznasz, że przecież nie zmieni to wartości tej zmiennej. Dokładnie to teraz robisz. Trzeba zastosować podejście ze wskaźnikami:

Kopiuj
void funkcja(int_ptr_t *wskaznik) {
  *wskaznik = jakas_tam_wartosc;
}

A do funkcji przesłać adres:

Kopiuj
funkcja(&jakis_wskaznik);

W rzeczywistości masz teraz podwójny wskaźnik, ale nie ma to dla Ciebie znaczenia, bo ten pierwszy jest ukryty przez typedef i piszesz "normalnie".

(Przykład: http://ideone.com/OJDmqh)


"(...) otherwise, the behavior is undefined".
edytowany 2x, ostatnio: Endrju
RE
taka prosta rzecz do zrozumienia - w C wszystkie argumenty są przekazywane jako wartość i kopiowane, również wskaźniki ;).
Endrju
Dodałem więcej wyjaśnień. ;-)
marcinmierzejewski1024
Endrju: Dzieki, prowadzący stwierdził że wszystkie funkcje mają byc typu void a jak ktoś zrobi innaczej to nawet nie ma co oddawać wejsciowki.. kolega zrobił tak że przeładowane funkcje przyjmują jako argumenty to samo ale nawet nic z tym argumentem nie robi tylko operuje na zmiennych globalnych - bez sensu, no nie? no ale 5 dostał: F Rev: Faktycznie działa to jakby było jak mowisz- dzieki za uświadomienie.
Endrju
No dobrze. W takim razie zastosuj to podejście, które jest w przykładzie - potrzebujesz podwójnego wskaźnika.
marcinmierzejewski1024
  • Rejestracja:prawie 13 lat
  • Ostatnio:ponad 2 lata
  • Postów:14
0
Kopiuj
void create(test **wskaznik,int ile)
	{
	*wskaznik=(test *)malloc(ile*sizeof(test));
	int i=0;
	for(i=0;i<ile;i++)
		{
		*wskaznik[i].liczba=i;// tutaj sie wywala
		}
	} 

create((test **)&wsk2,5);

Faktycznie teraz zmienia adres, ale mam problem- podejrzewam że chodzi o coś z priorytetem operatorów ale jak wciskam jakieś nawiasy w "*wskaznik[i].liczba=i;" to debbuger mowi coś że bledne typowanie.

Piwo Ci wisze, jakbyś był kiedyś w Szczecinie to daj znać: )

marcinmierzejewski1024
((*wskaznik)+i)->liczba=i; - rozwiazało problem: )
Endrju
Tak, ale to jest mniej czytelne - po to jest []. ;-)
_13th_Dragon
  • Rejestracja:prawie 20 lat
  • Ostatnio:21 dni
1

Jest jeszcze jeden sposób:

Kopiuj
struct TabelaTest
  {
   Test *wskaznik;
   unsigned Ile;
  };

void create(struct TabelaTest *tabela,unsigned Ile) ...
 void get(struct TabelaTest *tabela) ...
void destroy(struct TabelaTest *tabela) ...

w main robisz:

Kopiuj
   TabelaTest T;
  create(&T,10);
  get(&T);
  destroy(&T);

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
Endrju
  • Rejestracja:około 22 lata
  • Ostatnio:prawie 2 lata
1

Faktycznie teraz zmienia adres, ale mam problem- podejrzewam że chodzi o coś z priorytetem operatorów ale jak wciskam jakieś nawiasy w "*wskaznik[i].liczba=i;" to debbuger mowi coś że bledne typowanie.

Operator [] ma wyższy priorytet od *. Dlatego najpierw musisz zrobić dereferencję a dopiero potem możesz posługiwać się tym jak tablicą. Powinno być (*wskaznik)[i].liczba = i;


"(...) otherwise, the behavior is undefined".
edytowany 1x, ostatnio: Endrju
_13th_Dragon
  • Rejestracja:prawie 20 lat
  • Ostatnio:21 dni
0

Można to rozwiązać w bardziej elegancki sposób aby nie robić dodatkowych operacji w pętli:

Kopiuj
test *wsk=(test *)malloc(ile*sizeof(test));
*wskaznik=wsk;
...
wsk[i].liczba=i;

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
Endrju
Nie wydaje Ci się, że kompilator sam na to wpadnie? (Nazywa się to common subexpression elimination) Aczkolwiek jest to ładniejsze, to prawda.
_13th_Dragon
Staram się wyręczać kompilator tam gdzie to nie zmniejsza czytelności, a tam gdzie zwiększa czytelność to nawet się nie zastanawiam.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.