2010-09-19 23 views
12

iOS/Objective-C: J'ai un grand nombre de valeurs booléennes.Comment implémenter un tableau de bits dans C/Objective C

Il s'agit d'un moyen inefficace de stocker ces valeurs - au moins huit bits sont utilisés pour chaque élément lorsqu'un seul est nécessaire.

Comment puis-je optimiser?

+1

Avez-vous essayé de chercher à voir si quelqu'un a écrit quelque chose que vous pouvez utiliser? Les gens ne vont pas simplement écrire votre code pour vous. –

+2

J'essayais en fait de partager du code que j'avais écrit en posant une question et en y répondant, mais ce site est si rapide !!! dans les 10 minutes il m'a fallu rassembler ma réponse, déjà deux réponses sont apparues! –

+0

SO n'est pas destiné à poser des questions que vous pouvez répondre vous-même. Et même alors, vous pourriez envisager de regarder ce qui existe sur le sujet sur le web et de comparer votre approche de ce que vous trouvez, d'abord. –

Répondre

14

voir CFMutableBitVector/CFBitVector pour une option CFTYPE

+2

http://developer.apple.com/library/mac/#documentation/CoreFoundation/Reference/CFBitVectorRef/Reference/reference.html – JeremyP

+0

Mais ces classes stockent des objets CFBit, qui sont typedeffed à 32 bits ints. Cette solution gaspille donc autant de mémoire. –

+8

@whitman les valeurs sont transmises comme CFBit; cela ne signifie pas qu'ils sont * stockés * en tant que tels. Je viens de regarder la mise en œuvre de CFBitVector (r.550.13). la consommation de mémoire est un bit, tandis que les tailles d'allocations sont arrondies à un nombre divisible par 64. une implémentation très conservatrice dans l'ensemble. – justin

6

Vous utilisez les opérations logiques bit à bit et le décalage de bits. (Une recherche Google pour ces termes peut vous donner quelques exemples.)

Fondamentalement, vous déclarez un type entier (y compris int, char, etc.), vous entier « shift » valeurs au bit que vous voulez, alors vous faites un OU ou un ET avec l'entier.

Quelques exemples rapides (en C++):

inline bool bit_is_on(int bit_array, int bit_number) 
{ 
    return ((bit_array) & (1 << bit_number)) ? true : false; 
} 

inline void set_bit(int &bit_array, int bit_number) 
{ 
    bit_array |= (1 << bit_number); 
} 

inline void clear_bit(int &bit_array, int bit_number) 
{ 
    bit_array &= ~(1 << bit_number); 
} 

Notez que cela fournit des "tableaux de bits" de taille constante (sizeof(int) * 8 bits). Peut-être que c'est OK pour vous, ou peut-être que vous voulez construire quelque chose en plus de cela. (Ou réutiliser tout ce que fournit une bibliothèque.)

Ceci utilisera moins de mémoire que les tableaux bool ... CEPENDANT ... Le code généré par le compilateur pour accéder à ces bits sera plus grand et plus lent. Donc, à moins d'avoir un grand nombre d'objets qui ont besoin de contenir ces tableaux de bits, cela pourrait avoir un impact négatif sur la vitesse et l'utilisation de la mémoire.

+1

La question n'est pas étiquetée C++. Peut-être que vous devriez convertir votre code en C. – JeremyP

+2

@JeremyP - C'était un exemple illustratif de toute façon. J'ai décidé d'utiliser des références plutôt que des pointeurs parce que je pensais que cela détournerait moins l'attention de la question posée. Je crois que le message a été bien reçu, et la réponse n'était pas destinée à être copiée-collée dans la solution de quelqu'un de toute façon. – asveikau

+4

la question est à propos de C. Le questionneur pourrait même pas savoir ce qu'est une référence. Si c'est le cas, vous n'avez pas distrait moins, vous avez distrait plus. – JeremyP

11

Essayez ceci:

#define BITOP(a,b,op) \ 
((a)[(size_t)(b)/(8*sizeof *(a))] op ((size_t)1<<((size_t)(b)%(8*sizeof *(a))))) 

Ensuite, pour tout ensemble d'éléments entiers non signés ne dépassant pas size_t, la BITOP macro peut accéder au tableau comme un tableau de bits . Par exemple:

unsigned char array[16] = {0}; 
BITOP(array, 40, |=); /* sets bit 40 */ 
BITOP(array, 41, ^=); /* toggles bit 41 */ 
if (BITOP(array, 42, &)) return 0; /* tests bit 42 */ 
BITOP(array, 43, &=~); /* clears bit 43 */ 

etc.

+1

Et remplacez les 8 avec CHAR_BIT si vous vous souciez de la portabilité complète à tout environnement C. –

+0

En fait, 8 fonctionne très bien partout si cela ne vous dérange pas de gaspiller des bits sur des plates-formes où 'CHAR_BIT> 8', et il donnera de meilleures performances que d'introduire des choses comme la division par 9 ou 10 ... –

+0

= ~ qui est deux opérateurs, & = et ~, vous devez envelopper la dernière moitié de la macro dans un autre ensemble de parens. Sinon, vous écrivez quelque chose que vous ne voulez pas dire. '#define BITOP (a, b, op) ((a) [(taille_t) (b)/(8 * taille de * (a))] op ((taille_t) 1 << ((taille_t) (b)% (8 * sizeof * (a))))) ' –

0

je suis tombé sur cette question que je vous écris un cadre de tableau de bits qui est l'intention de gérer de grandes quantités de « bits » similaire à Java BitSet. Je cherchais à voir si le nom que j'avais choisi était en conflit avec d'autres frameworks Objective-C.

Quoi qu'il en soit, je commence juste cela et je décide de publier sur SourceForge ou d'autres sites d'hébergement open source.

Faites-moi savoir si vous êtes intéressé

Edit: J'ai créé le projet, appelé BitArray, sur SourceForge. La source est dans le référentiel SF SVN et j'ai également téléchargé un framework compilé. Ce LINK obtiendra votre là.

  • Frank
2
#define BITOP(a,b,op) \ 
    ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) 

ne fonctionnera pas ...

Fix:

#define BITOP(a,b,op) \ 
((a)[(size_t)(b)/(8*sizeof *(a))] op ((size_t)1<<((size_t)(b)%(8*sizeof *(a)))))