Czy są jakieś wady przekazywania struktur przez wartość w C, zamiast przekazywania wskaźnika?
Jeśli struktura jest duża, istnieje oczywiście aspekt wydajności kopiowania dużej ilości danych, ale w przypadku mniejszej struktury powinno to być to samo, co przekazywanie kilku wartości do funkcji.
Może być nawet bardziej interesujący, gdy jest używany jako wartości zwracane. C ma tylko pojedyncze wartości zwracane przez funkcje, ale często potrzebujesz kilku. Zatem prostym rozwiązaniem jest umieszczenie ich w strukturze i zwrócenie jej.
Czy są jakieś powody za lub przeciw?
Ponieważ może nie być oczywiste dla wszystkich, o czym mówię, podam prosty przykład.
Jeśli programujesz w C, prędzej czy później zaczniesz pisać funkcje, które wyglądają tak:
void examine_data(const char *ptr, size_t len)
{
...
}
char *p = ...;
size_t l = ...;
examine_data(p, l);
To nie jest problem. Jedynym problemem jest to, że musisz uzgodnić ze swoim współpracownikiem, w jakiej kolejności powinny być parametry, więc używasz tej samej konwencji we wszystkich funkcjach.
Ale co się dzieje, gdy chcesz zwrócić te same informacje? Zwykle dostajesz coś takiego:
char *get_data(size_t *len);
{
...
*len = ...datalen...;
return ...data...;
}
size_t len;
char *p = get_data(&len);
Działa to dobrze, ale jest znacznie bardziej problematyczne. Wartość zwracana jest wartością zwracaną, z wyjątkiem tego, że w tej implementacji tak nie jest. Z powyższego nie można stwierdzić, że funkcja get_data nie może sprawdzić, na co wskazuje len. I nie ma nic, co sprawia, że kompilator sprawdza, czy wartość jest faktycznie zwracana przez ten wskaźnik. Więc w przyszłym miesiącu, gdy ktoś inny modyfikuje kod bez jego zrozumienia (ponieważ nie przeczytał dokumentacji?), Ulega on zepsuciu i nikt nie zauważa, lub zaczyna się losowo zawieszać.
Zatem rozwiązanie, które proponuję, to prosta struktura
struct blob { char *ptr; size_t len; }
Przykłady można przepisać w następujący sposób:
void examine_data(const struct blob data)
{
... use data.tr and data.len ...
}
struct blob = { .ptr = ..., .len = ... };
examine_data(blob);
struct blob get_data(void);
{
...
return (struct blob){ .ptr = ...data..., .len = ...len... };
}
struct blob data = get_data();
Z jakiegoś powodu myślę, że większość ludzi instynktownie sprawiłaby, że exam_data wziąłby wskaźnik do struct blob, ale nie rozumiem dlaczego. Wciąż otrzymuje wskaźnik i liczbę całkowitą, jest po prostu znacznie wyraźniejsze, że idą razem. A w przypadku get_data nie można zepsuć w sposób, który opisałem wcześniej, ponieważ nie ma wartości wejściowej dla długości, a musi być zwrócona długość.
gettimeofday
), zamiast tego używają wskaźników, a ludzie biorą to jako przykład.
void examine data(const struct blob)
jest błędne.