Implementare bitmap

Am început curând curățarea proiectelor mele și am decis că vreau să creez un depozit personal de biți utili de cod. Am găsit acest cod bitmap între ele și l-am editat puternic și aș aprecia dacă cineva ar putea să-l revizuiască, pentru că nu sunt atât de obișnuit la operațiile bit și altele. Codul este suficient de portabil sau ar trebui să existe modificări?

bitmap.h

#ifndef BITMAP__ #define BITMAP__ #define BIT (8*sizeof(byte)) #define BITMAP_NOTFOUND -1 typedef enum{false=0, true} bool; typedef unsigned char byte; bool bitmapGet (byte *, int); void bitmapSet (byte *, int); void bitmapReset (byte *, int); int bitmapSearch(byte *, bool, int, int); #endif 

bitmap.c

#include "bitmap.h" static bool get (byte, byte); static void set (byte *, byte); static void reset(byte *, byte); /* CAREFUL WITH pos AND BITMAP SIZE! */ bool bitmapGet(byte *bitmap, int pos) { /* gets the value of the bit at pos */ return get(bitmap[pos/BIT], pos%BIT); } void bitmapSet(byte *bitmap, int pos) { /* sets bit at pos to 1 */ set(&bitmap[pos/BIT], pos%BIT); } void bitmapReset(byte *bitmap, int pos) { /* sets bit at pos to 0 */ reset(&bitmap[pos/BIT], pos%BIT); } int bitmapSearch(byte *bitmap, bool n, int size, int start) { /* Finds the first n value in bitmap after start */ /* size is the Bitmap size in bytes */ int i; /* size is now the Bitmap size in bits */ for(i = start+1, size *= BIT; i < size; i++) if(bitmapGet(bitmap,i) == n) return i; return BITMAP_NOTFOUND; } static bool get(byte a, byte pos) { /* pos is something from 0 to 7*/ return (a >> pos) & 1; } static void set(byte *a, byte pos) { /* pos is something from 0 to 7*/ /* sets bit to 1 */ *a |= 1 << pos; } static void reset(byte *a, byte pos) { /* pos is something from 0 to 7*/ /* sets bit to 0 */ *a &= ~(1 << pos); } 

Comentarii

  • Pentru oricine care urmărește în continuare această postare, am dat codul github aici . Am adăugat, de asemenea, toate comentariile dvs. ca probleme. Vă mulțumim pentru comentarii și voi începe să le implementez.

Răspundeți

Dacă vă așteptați ca codul dvs. să fie vreodată folosit din C ++ (care este o mulțime de cod C), atunci nu ar trebui să utilizați niciun identificator cu o subliniere dublă.

#ifndef BITMAP__ // ^^ May cause problems in C++ 

Deoarece acest lucru este rezervat pentru implementare în C ++. De asemenea, termenul BITMAP este foarte generic și este foarte probabil să vă confruntați cu alte biblioteci și încercați să îl faceți mai unic proiectului dvs.

Presupuneți că un caracter este de 8 biți.

#define BIT (8*sizeof(byte)) 

Standardul nu spune acest lucru (este de cel puțin 8 biți), dar este de fapt definit prin macro CHAR_BITS, așa că ar trebui să utilizați:

#define BIT (CHAR_BITS*sizeof(byte)) 

Fișierul dvs. antet este modul în care majoritatea oamenilor vă vor vedea mai întâi codul și vor încerca să înțeleagă cum să îl utilizați. Astfel, introducerea numelor parametrilor în fișierul antet este probabil o idee bună, deoarece ajută la documentarea utilizării lor.

bool bitmapGet (byte *, int); void bitmapSet (byte *, int); void bitmapReset (byte *, int); int bitmapSearch(byte *, bool, int, int); 

Acțiunea suplimentară a bitmapSearch nu este evident, astfel încât un comentariu despre utilizarea sa în antet ar fi probabil o idee bună. De fapt, o mică idee despre modul în care primul parametru poate fi o matrice ar fi probabil o idee bună (deoarece nu este evident fără a citi codul).

Aveți grijă la comentarii:

/* pos is something from 0 to 7*/ 

Acest lucru este adevărat numai dacă faceți ipoteze (A: acea dimensiune (octet) == 1 B: înmulțiți acest lucru cu 8). Comentariul ar fi trebuit să fie:

/* pos is a value between [0, BIT) */ 

Rețineți utilizarea „[” în stânga și „)” în dreapta. Este o notație matematică care indică faptul că 0 este inclus și BIT nu este inclus în interval (este obișnuit atât în documentația C / C ++).

Răspuns

  1. Tipurile dvs. sunt inutile – folosiți doar caractere nesemnate și int așa cum ar face biblioteca standard.

  2. Pe același subiect, enum bool nu este necesar deoarece în C diferit de zero indică starea adevărată. Îl confirmați singur, deoarece get () presupune că valoarea 1 este adevărată. Toată lumea își asumă acest lucru și astfel tipul este redundant. Mai mult, este greșit și pentru că dacă îți schimb enum-ul în

    typedef enum{true=0, false} bool; 

    funcția ta eșuează, chiar dacă este logic un lucru rezonabil de făcut.

    Dacă doriți să utilizați un astfel de bool, ar trebui să returnați una dintre valorile sale în mod explicit:

    return ((a >> pos) & 1) ? true : false; 

    dar nu are niciun rost în acest sens. Returnați doar un int așa cum ar face biblioteca standard.

  3. bitmapGet () returnarea unui bool mi se pare greșit. Biții bitmap au valori 1 și 0, nu sunt adevărate și false (chiar dacă acestea sunt în prezent aceleași). Numirea acestuia bitmapIsSet () ar fi mai logică.

  4. sizeof (char) este 1 prin definiție, deci BIT poate fi înlocuit cu CHAR_BIT

  5. Parantezele de deschidere pentru funcții sunt în mod normal la coloana 0

  6. Ordinea parametrilor pentru bitmapSearch ar fi mai logică, este dimensiunea urmată la care se referă (bitmap).

  7. Parametrul de pornire pentru bitmapSearch este greșit. Pentru a specifica o căutare începând de la bitul 0 (cu siguranță cea mai obișnuită), apelantul trebuie să treacă -1 !!

  8. De ce să treci parametrul „pos” ca „octet”? Ați definit „octet” pentru a reprezenta octeții bitmap și „poz” nu este cu siguranță unul dintre acestea. Veți primi avertismente ale compilatorului dacă sunt activate (ar trebui să fie) cu privire la transmiterea argumentelor cu lățimi diferite datorită prototipurilor. Și restricționarea „poz” la un octet poate adăuga o instrucțiune suplimentară a mașinii (uitați-vă la asamblare) în timp ce nu obțineți nimic. Dacă ați putea defini un tip pos_t cu intervalul 0..7 pe care pareți să-l doriți, atunci puteți argumenta că a fost într-un fel corect, dar, deoarece nu puteți face acest lucru în C și clar valoarea octetului are intervalul 0 .. 255, nu este mai bine decât să folosiți un int.

Răspuns

Do didn „t întrebați despre performanță, dar puteți accelera bitmapSearch pentru bitmap-uri rare, uitându-vă mai întâi la un octet la un moment dat. Dacă căutați un 1, puteți sări peste octeți care sunt 0x00 și dacă în căutarea unui 0, puteți sări peste octeți care sunt 0xFF. După aceea, puteți scana biții de pe următorul octet sau puteți utiliza un tabel de căutare pe acesta.

În ceea ce privește API-ul, puteți adăuga

byte * bitmapAlloc(int sizeInBits); void bitmapFree(byte * bitmap); 

, astfel încât clientul să nu fie nevoit să vă faceți griji cu privire la câte octeți trebuie să allocate.

Și / sau furnizați o macrocomandă pentru a vă ajuta cu alocările. O macrocomandă în loc de o funcție dacă doriți să apară în alocările matricei.

#define BITMAP_BYTE_COUNT_FOR(n) ((n)+BIT-1)/BIT) 

I „d am, de asemenea, bitmapSearch ia dimensiunea sa ca număr de biți în loc de număr de octeți. Apoi, dacă clientului îi pasă doar, să zicem, de 26 de biți pentru litere, nu trebuie să vă faceți griji cu privire la căutarea care returnează 27, deoarece harta de biți are într-adevăr 32 de biți.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *