Bitmap-implementering (Norsk)

Jeg begynte nylig med å rydde opp i prosjektene mine og bestemte meg for at jeg vil opprette et personlig lager med nyttige kodebiter. Jeg fant denne bitmappekoden mellom dem og redigerte den tungt, og jeg setter pris på om noen kan se gjennom den, for jeg er ikke den som pleide å bruke bitvis operasjoner og slikt. Er koden bærbar nok, eller burde det være endringer?

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); } 

Kommentarer

  • Til alle som fremdeles følger dette innlegget, forpliktet jeg koden til github her . Jeg la også til alle kommentarene dine som problemer. Takk for kommentarene dine, og jeg vil begynne å implementere dem.

Svar

Hvis du forventer at koden din noen gang vil være brukt fra C ++ (som mye C-kode er), bør du ikke bruke noen identifikatorer med dobbelt understrek.

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

Da dette er reservert for implementeringen i C ++. Begrepet BITMAP er også veldig generisk, og det er sannsynlig at du kommer til å kollidere med andre biblioteker, og prøv å gjøre det mer unikt for prosjektet ditt.

Du antar at en røye er 8 biter.

#define BIT (8*sizeof(byte)) 

Standarden sier ikke dette (den er minst 8 bits), men den defineres faktisk via makroen CHAR_BITS, så du bør bruke:

#define BIT (CHAR_BITS*sizeof(byte)) 

Overskriftsfilen din er hvordan folk flest først vil se koden din og prøve å forstå hvordan du bruker den. Dermed er det sannsynligvis en god ide å sette parameternavnene i toppfilen, da det hjelper med å dokumentere bruken av dem.

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

Ytterligere handlingen til bitmapSearch er ikke opplagt, og det vil sannsynligvis være en god ide å kommentere bruken i toppteksten. Egentlig en liten uklarhet om hvordan den første parameteren kan være en matrise, vil sannsynligvis være en god ide (da det ikke er åpenbart uten å lese koden).

Vær forsiktig med kommentarer:

/* pos is something from 0 to 7*/ 

Dette gjelder bare hvis du antar antakelser (A: størrelsen på (byte) == 1 B: du multipliserer dette med 8). Kommentaren burde ha vært:

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

Legg merke til bruken av «[» til venstre og «)» til høyre. Det er en matematisk notasjon som indikerer at 0 er inkludert og BIT ikke er inkludert i området (det er vanlig i både C / C ++ -dokumentasjon).

Svar

  1. Dine typer er unødvendige – bruk bare usignert røye og int som standardbiblioteket ville gjort.

  2. Om det samme emnet er din enum bool unødvendig fordi i C ikke-null indikerer den sanne tilstanden. Du bekrefter det selv fordi get () antar at verdien 1 er sann. Alle antar dette, og så er typen overflødig. Dessuten er det også galt, for hvis jeg endrer enum til

    typedef enum{true=0, false} bool; 

    mislykkes din funksjon, selv om det logisk sett er en rimelig ting å gjøre.

    Hvis du vil bruke en slik bool, bør du returnere en av dens verdier eksplisitt:

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

    men det er egentlig ikke noe poeng i dette. Bare returner et int som standardbiblioteket ville gjort.

  3. bitmapGet () å returnere en bool virker feilnavn for meg. Bitmapbitene har verdiene 1 og 0, ikke sanne og falske (selv om disse for øyeblikket er de samme). Å kalle det bitmapIsSet () ville være mer logisk.

  4. sizeof (char) er per definisjon 1, slik at BIT kan erstattes med CHAR_BIT

  5. Åpningsbraketter for funksjoner er normalt i kolonne 0

  6. Parameterrekkefølgen for bitmapSearch vil være mer logisk er størrelsen fulgt av det den refererer til (bitmap).

  7. Startparameteren for bitmapSearch er feil. For å spesifisere et søk som starter fra bit 0 (sikkert den vanligste) må innringeren passere -1 !!

  8. Hvorfor sende «pos» -parameteren som en «byte»? Du har definert «byte» til å representere bitmap-byte, og «pos» er absolutt ikke en av dem. Du vil få kompilatoradvarsler hvis de er aktivert (de burde være) om å sende argumenter med forskjellige bredder på grunn av prototyper. Og å begrense «pos» til en byte kan legge til en ekstra maskininstruksjon (se på montøren) mens du ikke oppnår noe. Hvis du kunne definere en type pos_t med området 0..7 som du ser ut til å ønske, kan du argumentere for at det på en eller annen måte var riktig, men da du ikke kan gjøre det i C og tydelig har byteverdien området 0 .. 255, er det ikke bedre enn å bruke et int.

Svar

Gjorde det ikke spør om ytelse, men du kan øke hastigheten bitmapSearch for sparsomme bitmapper ved å først se på en byte om gangen. Hvis du leter etter en 1, kan du hoppe over byte som er 0x00, og hvis Når du ser etter en 0, kan du hoppe over byte som er 0xFF. Etter det kan du skanne bitene på neste byte eller bruke en oppslagstabell på den.

Så langt som API går, kan du legge til

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

slik at klienten ikke trenger å bekymre seg for hvor mange byte som skal allokere.

Og / eller gi en makro for å hjelpe med tildelinger. En makro i stedet for en funksjon hvis du vil at den skal vises i arrayallokeringer.

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

I «d also have bitmapSearch ta størrelsen som bit-count i stedet for byte count. Hvis klienten bare bryr seg om for eksempel 26 biter for bokstaver, trenger de ikke å bekymre seg for et søk som returnerer 27 fordi bitmappen virkelig har 32 biter i seg.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *