Jak porównać struktury równości w C?
Jak porównać dwie instancje struktur równości w standardzie C?
11 answers
C nie zapewnia żadnych udogodnień językowych, aby to zrobić - musisz to zrobić sam i porównać każdy członek struktury po członku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 20:22:14
Możesz ulec pokusie użycia memcmp(&a, &b, sizeof(struct foo))
, ale może nie działać we wszystkich sytuacjach. Kompilator może dodać przestrzeń bufora wyrównania do struktury, a wartości Znalezione w miejscach pamięci leżących w przestrzeni bufora nie są gwarantowane jako żadna konkretna wartość.
Ale jeśli użyjesz calloc
lub memset
pełnego rozmiaru struktur przed ich użyciem, możesz zrobićpłytkie porównanie z memcmp
(jeśli twoja struktura zawiera wskaźniki, będzie pasować tylko wtedy, gdy adres wskaźniki są wskazuje na to samo).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-22 06:51:25
Jeśli robisz to dużo, sugerowałbym napisanie funkcji porównującej obie struktury. W ten sposób, jeśli kiedykolwiek zmienisz strukturę, wystarczy zmienić porównanie w jednym miejscu.
Jak to zrobić.... Musisz porównać każdy element indywidualnie
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 20:24:32
Nie można używać memcmp do porównywania struktur pod kątem równości z powodu potencjalnych losowych znaków wypełnienia między polami w strukturach.
// bad
memcmp(&struct1, &struct2, sizeof(struct1));
Powyższa struktura zawiedzie dla takiej struktury:
typedef struct Foo {
char a;
/* padding */
double d;
/* padding */
char e;
/* padding */
int f;
} Foo ;
Aby być bezpiecznym, musisz użyć porównań między użytkownikami.
Uwaga możesz używać memcmp() na statycznych stykach bez martwienie się o padding, o ile nie inicjalizujesz wszystkich członków (jednocześnie). Jest to zdefiniowane przez C90:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 20:52:38
@Greg ma rację, że trzeba pisać jawne funkcje porównawcze w ogólnym przypadku.
Możliwe jest użycie memcmp
Jeśli:
- struktury nie zawierają pól zmiennoprzecinkowych, które mogą być
NaN
. - struktury nie zawierają wypełnienia (użyj
-Wpadded
z clang aby to sprawdzić) lub struktury są jawnie inicjalizowane za pomocąmemset
podczas inicjalizacji. - nie ma typów członkowskich (takich jak Windows
BOOL
), które mają różne, ale równoważne wartości.
Jeśli nie programujesz systemów wbudowanych (lub piszesz bibliotekę, która może być na nich używana), nie martwiłbym się o niektóre narożne przypadki w standardzie C. Różnica między wskaźnikiem bliskim a Dalekim nie istnieje na żadnym urządzeniu 32 - lub 64-bitowym. Żaden nie Wbudowany system, o którym wiem, nie ma wielu NULL
wskaźników.
Inną opcją jest automatyczne generowanie funkcji równości. Jeśli zdefiniujesz strukturę w prosty sposób, możliwe jest użycie proste przetwarzanie tekstu do obsługi prostych definicji struktur. Możesz użyć libclang dla ogólnego przypadku – ponieważ używa tej samej nakładki co clang, obsługuje wszystkie przypadki narożne poprawnie (z wyjątkiem błędów).
Nie widziałem takiej biblioteki generującej kod. Wydaje się to jednak stosunkowo proste.
Jest jednak również tak, że takie generowane funkcje równości często robiłyby złe rzeczy na poziomie aplikacji. Na przykład, należy porównać dwie struktury UNICODE_STRING
w systemie Windows płytko czy głęboko?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-23 19:16:03
memcmp
memcmp
nie porównuje struktury, memcmp
porównuje binarne, a w strukturze zawsze są śmieci, dlatego zawsze wychodzi False w porównaniu.
Porównaj element po elemencie jego bezpieczny i nie zawiedzie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-03 09:03:28
Jeśli struktury zawierają tylko pierwiastki lub jeśli interesuje Cię ścisła równość, możesz zrobić coś takiego:
int my_struct_cmp(const struct my_struct * lhs, const struct my_struct * rhs) { return memcmp(lhs, rsh, sizeof(struct my_struct)); }
Jednakże, jeśli Twoje struktury zawierają wskaźniki do innych struktur lub związków, będziesz musiał napisać funkcję, która porównuje primitives odpowiednio i wykonać wywołania porównawcze z innymi strukturami.
Pamiętaj jednak, że powinieneś użyć memset(&a, sizeof(struct my_struct), 1), aby zerować zakres pamięci struktury jako część inicjalizacji ADT.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 20:34:40
Zależy od tego, czy pytanie, które zadajesz, brzmi:
- czy te dwie struktury to ten sam obiekt? Czy mają taką samą wartość?
Aby sprawdzić, czy są one tym samym obiektem, porównaj wskaźniki do dwóch struktur równości. Jeśli chcesz dowiedzieć się ogólnie, czy mają taką samą wartość, musisz zrobić głębokie porównanie. Polega to na porównaniu wszystkich członków. Jeśli członkowie są wskaźnikami do innych struktur, musisz rekurencyjnie wprowadzić je do tych struktur też.
W szczególnym przypadku, gdy struktury nie zawierają wskaźników, można wykonać memcmp, aby wykonać bitowe porównanie danych zawartych w każdej z nich bez konieczności wiedzy, co oznaczają dane.
Upewnij się, że wiesz, co oznacza 'equals' dla każdego elementu - jest to oczywiste dla Int, ale bardziej subtelne, jeśli chodzi o wartości zmiennoprzecinkowe lub typy zdefiniowane przez użytkownika.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-27 14:41:58
Jeśli zmienna 2 structures jest inicjalizowana przez calloc lub jest ustawiona na 0 przez memset, więc możesz porównać swoje 2 struktury z memcmp i nie ma obaw o śmieci struktury, a to pozwoli Ci zarobić czas
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-03 09:11:00
Ten zgodny przykład wykorzystuje rozszerzenie kompilatora pakietów # pragma z Microsoft Visual Studio, aby zapewnić, że elementy struktury są pakowane tak szczelnie, jak to możliwe:
#include <string.h>
#pragma pack(push, 1)
struct s {
char c;
int i;
char buffer[13];
};
#pragma pack(pop)
void compare(const struct s *left, const struct s *right) {
if (0 == memcmp(left, right, sizeof(struct s))) {
/* ... */
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-30 17:06:41