I'm training a bit with C, and I'm trying to build a bit array. I would like to have some comments about my code, because I'm not sure that it's the best way to do it.
// BAL.c
#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "BAL.h"
#define BAL_Mask(n) (1 << ((n) % CHAR_BIT))
#define BAL_Convert(n) ((n) / CHAR_BIT)
void
BAL_And(BAL_Array *p, BAL_Array *q)
{
assert(p != NULL);
assert(q != NULL);
for (size_t i = 0; i < p->nBits; ++i)
p->pBits[i] &= q->pBits[i];
}
_Bool
BAL_Any(BAL_Array *p)
{
assert(p != NULL);
for (size_t i = 0; i < p->nBits; ++i) {
if (BAL_Get(p, i) != 0)
return 1;
}
return 0;
}
_Bool
BAL_Compar(BAL_Array *p, BAL_Array *q)
{
assert(p != NULL);
assert(q != NULL);
if (p->nSize != q->nSize)
return 0;
for (size_t i = p->nBits; i > 0; --i) {
if (BAL_Get(p, i) != BAL_Get(q, i))
return 0;
}
return 1;
}
size_t
BAL_Count(BAL_Array *p)
{
assert(p != NULL);
size_t n = 0;
for (size_t i = 0; i < p->nBits; ++i) {
if (BAL_Get(p, i) != 0)
++n;
}
return n;
}
void
BAL_End(BAL_Array *p)
{
assert(p != NULL);
free(p->pBits);
free(p);
}
inline unsigned char
BAL_Get(BAL_Array *p, size_t i)
{
assert(p != NULL);
assert(i <= p->nBits);
return p->pBits[BAL_Convert(i)] & BAL_Mask(i);
}
inline size_t
BAL_GetSize(BAL_Array *p)
{
assert(p != NULL);
return p->nBits;
}
BAL_Array *
BAL_Init(size_t n)
{
assert(n > 0);
BAL_Array *p = malloc(sizeof *p);
assert(p != NULL);
p->nSize = BAL_Convert(n + CHAR_BIT - 1);
p->pBits = calloc(p->nSize, 1);
p->nBits = n;
return p;
}
BAL_Array *
BAL_Load(const char *s)
{
assert(s != NULL);
size_t size = strlen(s);
BAL_Array *pRet = BAL_Init(size);
for (size_t i = 0; i < size; ++i) {
if (s[i] == '1')
BAL_Set(pRet, i);
}
return pRet;
}
void
BAL_LShift(BAL_Array *p, size_t m)
{
assert(p != NULL);
for (size_t i = 0; i < p->nBits; ++i) {
p->pBits[i] >>= m;
p->pBits[i] |= BAL_Get(p, i + 1) ? 1 : 0;
}
}
void
BAL_Not(BAL_Array *p)
{
assert(p != NULL);
for (size_t i = 0; i < p->nBits; ++i)
p->pBits[i] = ~p->pBits[i];
}
void
BAL_Or(BAL_Array *p, BAL_Array *q)
{
assert(p != NULL);
assert(q != NULL);
for (size_t i = 0; i < p->nBits; ++i)
p->pBits[i] |= q->pBits[i];
}
void
BAL_Print(BAL_Array *p, unsigned char *pOut, size_t nMax)
{
assert(p != NULL);
assert(pOut != NULL);
size_t i;
for (i = 0; i < p->nBits && i < nMax; ++i)
pOut[i] = BAL_Get(p, i) ? '1' : '0';
pOut[i] = '\0';
}
inline void
BAL_Reset(BAL_Array *p, size_t i)
{
assert(p != NULL);
assert(i <= p->nBits);
p->pBits[BAL_Convert(i)] &= ~BAL_Mask(i);
}
void
BAL_RShift(BAL_Array *p, size_t m)
{
assert(p != NULL);
for (size_t i = 0; i < p->nSize; ++i) {
p->pBits[i] <<= m;
p->pBits[i] |= BAL_Get(p, i + 1) ? 1 : 0;
}
}
inline void
BAL_Set(BAL_Array *p, size_t i)
{
assert(p != NULL);
assert(i <= p->nBits);
p->pBits[BAL_Convert(i)] |= BAL_Mask(i);
}
void
BAL_Xor(BAL_Array *p, BAL_Array *q)
{
assert(p != NULL);
assert(q != NULL);
for (size_t i = 0; i < p->nBits; ++i)
p->pBits[i] ^= q->pBits[i];
}
Header file :
// BAL.h
#ifndef BAL_H
#define BAL_H
typedef struct {
unsigned char *pBits;
size_t nSize;
size_t nBits;
} BAL_Array;
void BAL_And (BAL_Array *, BAL_Array *);
_Bool BAL_Any (BAL_Array *);
_Bool BAL_Compar (BAL_Array *, BAL_Array *);
size_t BAL_Count (BAL_Array *);
void BAL_End (BAL_Array *);
unsigned char BAL_Get (BAL_Array *, size_t);
size_t BAL_GetSize (BAL_Array *);
BAL_Array *BAL_Init (size_t);
BAL_Array *BAL_Load (const char *);
void BAL_LShift (BAL_Array *, size_t);
void BAL_Not (BAL_Array *);
void BAL_Or (BAL_Array *, BAL_Array *);
void BAL_Print (BAL_Array *, unsigned char *, size_t);
void BAL_Reset (BAL_Array *, size_t);
void BAL_RShift (BAL_Array *, size_t);
void BAL_Set (BAL_Array *, size_t);
void BAL_Xor (BAL_Array *, BAL_Array *);
#endif /* BAL_H */
Perhaps do you have other ideas ? Thanks.
assert
here. You should come up with a mechanism to indicate an error. Make yourvoid
methods returnint
(or_Bool
in your case) returning"true"
when successful or"false"
on failure. Come up with an "error code" to indicate what problem comes up or something similar if you want to convey that information to the programmer. – Jeff Mercado Jun 23 '12 at 20:54