2012-01-23 4 views
10

Dzisiaj natknąłem się na sytuację, w której musiałem zdecydować, czy cała struktura składająca się z około 40 elementów wynosi zero - co oznacza, że ​​każdy z elementów wynosi zero.
Myśląc jak zrobić to tak szybko i sprawnie, jak to możliwe, myślałem o 3 różnych sposobów, aby to zrobić:Preferowany sposób porównywania struktury do zera

  1. porównanie każdy element na zero, co skutkuje 40 if.
  2. przydzielanie podobnej struktury, która jest już wyzerowana, i memcmp ze strukturą.
  3. zawijanie struktury w związku z typem wystarczająco dużym, aby pokryć całość.

np

typedef union { 
    struct { 
    uint8_t a; 
    uint8_t b; 
    } 
    uint16_t c; 
} STRUCTURE_A; 

i porównując ją do zera.

Chciałbym wiedzieć, co myślisz o tych rozwiązaniach, które z nich uważasz za najszybsze i najbardziej wydajne.
A jeśli chodzi o lepsze podejście, proszę mi powiedzieć ...
Dzięki.

+0

Co jest nie tak z prostym sprawdzeniem całej struktury w wyrażeniu "if", tak jak w przypadku flagi zerowej? –

+3

Nie zapomnij o wyściółce! – NPE

+1

Czy wdrożyłeś każdy z trzech różnych sposobów i porównałeś ich wydajność? Co znalazłeś? –

Odpowiedz

15

Porównaj każdy członek struktury 0.

Jest to jedyny bezpieczny sposób na porównanie dwóch struktur obiektów (nawet jeśli jeden z obiektów struktura wszyscy członkowie ustawiona na wartość 0). Nie używaj memcmp do porównywania struktury, wartość bajtów dopełnienia w strukturze jest nieokreślona. Należy również zauważyć, że nie wolno używać operatora == z operandami obiektów struktury.

Zobacz ten link c-FAQ na temat porównania struktura obiektu:

Q: Is there a way to compare structures automatically?

+1

Jeśli upewniłeś się, że struktura nie zawiera dopełnienia, 'memcmp' jest bezpieczne. Podczas, gdy implementacja jest technicznie dopuszczalna, aby dodać dowolne bezsensowne wypełnienie, w rzeczywistym świecie dopełnienie jest wyłącznie do wyrównania, a prawidłowo skonstruowana, naturalnie wyrównana struktura nie będzie miała dopełnienia poza potencjalnie na końcu. W szczególności używanie 'intX_t' i zamawianie ich bez luk wyrównania jest dobrym sposobem na uniknięcie dopełnienia. –

+0

Jeśli struktura nie zawiera dopełnienia, a 'memcmp' faktycznie * jest * szybsza, optymalizator na pewno to zauważy i odpowiednio zmieni porównania. –

+0

Mam nadzieję, że ...... –

1

Jeśli rozmiar struktura jest < = wielkość słowo procesora, można zrobić unia sztuczka jednak żadnego dobrego kompilatora powinien to zrobić automatycznie, inaczej zwięzłoby to z if, co pozwoliło zachować przejrzystość, ale nadal zachowywać wydajność do zera.

0

Aby zapewnić klarowność kodu i, jak wskazali inni, aby uniknąć problemów spowodowanych wypełnianiem, sprawdzanie każdego członka byłoby najlepsze.

Aby uzyskać prędkość, zacznij od czegoś podobnego, które po prostu sprawdza każdy bajt, aby sprawdzić, czy jest zero.

int iszero(void * ptr, int bytes) 
{ 
    char * bptr = (char*)ptr; 
    while(bytes--) 
    if(*bptr++) 
     return 0; 
    return 1; 
} 

Następnie zoptymalizuj, aby porównywać według słów. Sprawdź przykłady implementacji newlib, takie jak strlen() & memcpy(), aby dowiedzieć się, jak to zrobić.

+0

Jest to odpowiednik 'memcmp' i może mieć problemy z dopełnieniem. –

+0

@R .. Nie, to nie jest odpowiednik memcmp(), ponieważ tutaj nie ma tu zerowej struktury o zbytecznej wartości. Dodatkowy dostęp do pamięci w memcmp() jest prawdopodobnie gorszy niż dwukrotny czas dostępu do pamięci, ponieważ robisz dwa odczyty za każdym razem I prawdopodobnie masz pamięć podręczną kosza na dużych strukturach. Nie brałem pod uwagę problemów z wyściółką. Ale jeśli wiesz, że nie ma dopełnienia (np. W GCC za pomocą pakietu pragma), podtrzymam argument, że ta technika jest najszybsza. –

+0

Przez "równoważny" rozumiem, że ma to samo zachowanie (i problem z dopełnieniem), ale zapraszam do porównania wydajności. Twój kod (bajt po bajcie) jest tak powolny, że nawet przy wielu odczytach powinien wygrać 'memcmp'. Dobry 'memcmp' porównuje 4, 8 lub nawet 16 bajtów naraz. BTW "pakowane" nie jest sposobem na naprawienie problemów z wyrównaniem. Mój komentarz na temat odpowiedzi ouah jest poprawny. –