2010-08-28 15 views
6

Mam C (nie C++) struct że idzie takC tablice struct

typedef struct mystruct{ 
float a,b; 
int x, y; 
} mystruct; 

Następnie w funkcji Zbieram dane tak:

mystruct List[MAX]; 
ListNumber = 0; 

for(i = 0; i < MAX; i++) 
{ 
if(conditions_meet) 
{ 
    List[ListNumber].a = masterlist[i].a; 

... itp

ListNumber++; 
} 
} 

potem wysłać tablicę do funkcji

DoStuff(static int max, mystruct array[max]){ 
    Stuff 
} 

To działa, ale gdy próbuję zrobić to tak ....

mystruct setter(int i) 
{ 
mystruct TEMP; 
TEMP.a = masterlist[i].a; 
//......etc 
return TEMP; 
} 


mystruct List[MAX]; 
ListNumber = 0; 

for(i = 0; i < MAX; i++) 
{ 
if(conditions_meet) 
{ 
    List[ListNumber] = setter(i); 
    ListNumber++; 
} 
} 

To powoduje wiele błędów odjazdowe. Dlaczego to się dzieje? edytuj: @ tommieb75 Nie mogę podać zbyt wiele szczegółów, wyniki nie wydają się mieć wzorca. Lista jest używana jako ogólny sposób rysowania elementów na ekranie, a posiadanie funkcji zamiast bezpośredniego ustawienia powoduje dziwne problemy z renderowaniem - i losowe - ale nie generuje żadnych błędów kompilatora. gdb pokazuje, że niektóre liczby całkowite są większe od liczb całkowitych, to jedyny wzorzec, jaki znajduję. masterlist to globalna tablica innej struktury. Dane muszą zostać przekonwertowane na strukturę w tym przykładzie. Brak ostrzeżeń lub błędów kompilatora. Mogę włączyć bardziej wrażliwe ostrzeżenia, ale zawsze dostaję zgłoszenia o ogólnym błędzie, jaki mogę sobie wyobrazić. Mam zamiar wypróbować wybrane rozwiązanie, które powinno wystarczyć. W każdym razie podobne funkcje zwracające structs są używane w moim kodzie i wszystkie działają idealnie, z wyjątkiem tego przypadku z tablicą struktur.

+1

mógłbyś pisać niektóre błędy są uzyskiwanie? – GameFreak

+0

Ktoś odświeżyć moją pamięć: Czy możesz zwrócić structs przez wartość w C? –

+2

dlaczego nie? wskaźniki powinny być szybsze, ale możesz zwrócić wartość. Btw. www.ideone.com i możesz sprawdzić ;-) – nilphilus

Odpowiedz

1

na proste ustawienie członkiem struct trzeba kopię z całego struct-elementu?

mystruct List[MAX]; 
ListNumber = 0; 

for(i = 0; i < MAX; i++) 
{ 
if(conditions_meet) 
{ 
    List[ListNumber].a = masterlist[i].a; 
    ListNumber++; 
} 
} 

Jeśli naprawdę potrzebujemy funkcji, należy użyć pamięci docelowy jako parametr jak:

void setter(mystruct *dest,const mystruct *src) 
{ 
    dest->a = src->a; 
} 
for(i = 0; i < MAX; i++) 
{ 
if(conditions_meet) 
{ 
    setter(&List[ListNumber], &masterlist[i]); 
    ListNumber++; 
} 
} 
+0

Tak, funkcja polega na wyczyszczeniu funkcji, to jest masywne trudne do odczytania i zmienić w szybki sposób. Jednak wydaje się to być interesującym rozwiązaniem, zamierzam to przetestować. – Balkania

1

co jest

mystruct setter(i) 
{ 
mystruct TEMP; 
TEMP.a = masterlist[i].a; 

'i' ma żadnego rodzaju?

// Jeśli wystąpią błędy z niezainicjowanych członków struktury, które mogą pomóc http://ideone.com/WRLVG

+1

Jest to pośrednio int. – Potatoswatter

+0

@ Argumenty za chatotos też? pamiętam o zwracanych wartościach, ale nie o argumentach (tak czy owak masz rację) – nilphilus

0

Pierwszym problemem jest twoja definicja seter nie jest podpis funkcji prawnej. Parametr i musi być przypisany typ

mystruct setter(int i) { 
    ... 
} 

wykorzystuje również zmienną masterlist, który nie jest zdefiniowany w funkcji. Może to być prawnie zadeklarowane w innym miejscu jako statyczne. Jeśli nie będzie to jednak trzeba mieć dostęp do funkcji w jakiś sposób

+0

Masterlist jest globalna. Nie znam właściwej nazwy w C, chociaż ... w każdym razie kod, który wpisałem, był najczęściej robiony "w locie", w przeciwnym razie byłby zbyt duży. – Balkania

+0

Również to nie było kopiuj-wklej rzeczywistego kodu, właśnie zrobiłem przykład w locie, aby usunąć cały otaczający hałas ... oczywiście, że to prawda, albo mój kompilator narzekał; P – Balkania

+0

@Blakania: Ty "Nie otrzymam żadnych użytecznych odpowiedzi, ponieważ twój wymyślony przykład zdaje się pomijać rzeczywisty problem. – caf

0

Problemem jest to, że wewnątrz funkcji setter masz stos przydzieloną zmienna TEMP które wykraczają poza zakres raz funkcja zwraca ... może być lepiej przeznaczyć wskaźnik my_struct na stercie i powrócić adres nim z powrotem do procedury wywołującej ...

Edit:

mystruct *setter(int i){ 
    mystruct *ptr_myStruct; 
    ptr_myStruct = malloc(sizeof(mystruct)); 
    if (ptr_myStruct != NULL){ 
     ptr_myStruct->a = masterlist[i].a 
     // etc... 
     return &ptr_myStruct; 
    } 
    return NULL; 
} 

mystruct List[MAX]; 
ListNumber = 0; 

for(i = 0; i < MAX; i++) 
{ 
if(conditions_meet) 
{ 
    List[ListNumber] = setter(i); 
    ListNumber++; 
} 
} 

to jest to, co jest potrzebne, aby uzyskać wartości z powrotem gdy rutynowe wyjście zgaśnie zakresu.To się nazywa powrót przez odwołanie

+0

Jest zwracany przez wartość. – Potatoswatter

+0

Różnica między wartością zwracaną i wartością zwracaną przez odniesienie ... to jest to, o czym mówię powyżej, poprzez zwrócenie adresu do przydzielonego wskaźnika na stercie, który jest zwracany przez odniesienie. – t0mm13b

+0

Gdyby powrócił przez odniesienie, wystąpiłby problem, ale na szczęście C nie ma tej funkcji. Jeśli funkcja return by value nie działała, prawdopodobnie nie pozwoliłaby na kompilację. – Potatoswatter