2012-01-23 7 views
10

Oggi mi sono imbattuto in una situazione in cui avevo bisogno di decidere se un'intera struttura che consiste di circa 40 elementi è zero - significa che ciascuno degli elementi è zero.
Quando si pensa come rendere più veloce ed efficiente possibile, ho pensato di 3 modi diversi per farlo:Modo preferito per confrontare una struttura a zero

  1. confrontare ogni elemento a zero, con conseguente 40 se dichiarazioni.
  2. allocando una struttura simile che è già azzerata e memcmp con la struttura.
  3. avvolgere la struttura in un'unione con un tipo abbastanza grande da coprire tutto.

per esempio

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

e poi confrontando a zero.

Mi piacerebbe sapere cosa ne pensi di queste soluzioni, quali di loro trovi più veloci e efficienti.
E se si tratta di un approccio migliore per favore dimmi ...
Grazie.

+0

Cosa c'è di sbagliato semplicemente controllando l'intera struttura in un'istruzione 'if', come si potrebbe per una bandiera zero? –

+3

Non dimenticare di imbottitura! – NPE

+1

Hai implementato ciascuno dei tuoi tre diversi modi e confrontato le loro prestazioni? Cosa hai trovato? –

risposta

15

Confronta tutti i membri della struttura a 0.

Questo è l'unico modo sicuro per confrontare due oggetti strutture (anche se uno degli oggetti di questa struttura è tutti i membri impostati al valore 0). Non utilizzare memcmp per confrontare una struttura, il valore dei byte del padding nella struttura non è specificato. Si noti inoltre che non è consentito utilizzare l'operatore == con gli operandi degli oggetti struttura.

Vedi questo link c-faq sul confronto struttura dell'oggetto:

Q: Is there a way to compare structures automatically?

+1

Se si è assicurato che la struttura non contenga padding, 'memcmp' è sicuro. Mentre un'implementazione è tecnicamente autorizzata ad aggiungere padding nonsense, nel mondo reale il padding è puramente per l'allineamento, e una struttura correttamente costruita e allineata naturalmente non avrà padding se non potenzialmente alla fine. In particolare, usare 'intX_t' e ordinarli senza spazi di allineamento è un buon modo per evitare qualsiasi riempimento. –

+0

Se la struttura non contiene padding e 'memcmp' in realtà * è * più veloce, l'ottimizzatore lo vedrà sicuramente e trasformerà i confronti di conseguenza. –

+0

Speriamo che ... –

1

Se la dimensione della struttura è < = la dimensione della parola del processore, si può fare la vostra unione trucco, però, nulla di buono compilatore dovrebbe farlo automaticamente, alias compatterebbe lo if, tenendo conto della chiarezza ma mantenendo comunque le prestazioni fino a zero.

0

Per chiarezza del codice, e come altri hanno sottolineato, per evitare problemi causati dal padding, controllare che ciascun membro sia il migliore.

Per velocità, iniziare con qualcosa di simile che controlla solo ogni byte per vedere se è zero.

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

Quindi ottimizzare per fare confronti allineati alla parola. Scopri l'implementazione di newlib di cose come strlen() & memcpy() per esempi su come è fatto.

+0

Questo è equivalente a 'memcmp' e potrebbe avere problemi di riempimento. –

+0

@R .. No, non è equivalente a memcmp() perché in questo caso non è presente una struttura a zero superfluo. L'accesso extra alla memoria in memcmp() è probabilmente peggio del doppio del tempo di accesso alla memoria perché si eseguono due letture ogni volta E probabilmente si ha un caching della cache su strutture di grandi dimensioni. Non avevo considerato i problemi di imbottitura. Ma se sai che non c'è padding (ad esempio in GCC usando pragma pack), rimarrò con la mia tesi che questa tecnica è la più veloce. –

+0

Per "equivalente" intendevo che ha lo stesso comportamento (e il problema di riempimento), ma vi invito a confrontare le prestazioni. Il tuo codice (byte per byte) è così lento che anche con più letture, 'memcmp' dovrebbe vincere. Un buon 'memcmp' confronta 4, 8 o anche 16 byte alla volta. BTW "imballato" non è il modo per risolvere i problemi di allineamento. Il mio commento sulla risposta di ouah è il modo corretto. –

Problemi correlati