Question

My task is to write a macro that checks how many elements in an array of INTs has excatly 5 bits that are on.

I know a macro is a very risky way of doing it, but that is the question that appears in some exams.

This is my code:

#include <stdio.h>
#define RESULT 5
#define SIZE 8
#define BITW(arr, length, counter)\
    int mask=0b00000001, bits=0, i=0, j=0;\
    for (i=0; i<length; i++){\
        for (j=0; j<sizeof(arr[i])*SIZE; j++){\
            if(mask&arr[i]>>j)\
                bits++;\
        }\
        if (bits==RESULT)\
            counter++;\
    }
int main(void){
    int arr[4]={0b11111000,0b11100011,0b11001100,0b11000000};
    int res=0; int counter=0;
    BITW(arr, 4, counter);
    printf("%d",counter);


}

The problem with macros is that I can't debug my code. I went over it a few times with no success but I realized I got the result 1 instead of 2.

The counter variable is the one that counts how many elements has 5 bits on. The bit variable counts in a certain element how many bits are on.

Thank you for your help.

Was it helpful?

Solution 2

The macro fails to set bits to zero before counting the bits in each array element. It sets bits to zero only before the loop over the entire array.

OTHER TIPS

I would probably do something like this, if you really want a macro:

static const int bits_per_nibble[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
#define BITS_PER_U8(x) (bits_per_nibble[(x) & 0xf] + bits_per_nibble[((x) >> 4) & 0xf])
#define BITS_PER_U16(x) (BITS_PER_U8((x) & 0xff) + BITS_PER_U8(((x) >> 8) & 0xff))
#define BITS_PER_U32(x) (BITS_PER_U16((x) & 0xffff) + BITS_PER_U16(((x) >> 16) & 0xffff))

Defining BITS_PER_U64 should be an obvious extension, if it's needed.

However, doing this as a small inline function would be a lot safer and a better solution...

There's also this, which has a whole section on ways to get the "population count" in various ways...

I said

if(mask&arr[i]>>j)\
    bits++;\

is wrong, because it tests if ANY bit in the result is set, not if all of them are set. I'd rewrite the code to count the number of bits in 1 byte to

bits=0;
for (mask=0b10000000; mask!=0; mask=mask>>1)
    if (arr[i]&mask)
        bits++;
if (bits==5)
    ...

Note this works only if mask is either unsigned or has more than 8 bits, so a char won't > do (your int is ok though).

but that was wrong.

However,

#define BITW(arr, length, counter)\
int mask=0b00000001, bits=0, i=0, j=0;\
for (i=0; i<length; i++){\
    bits=0;                         //<---- This line is missing from your code
    for (j=0; j<sizeof(arr[i])*SIZE; j++){\
        if(mask&arr[i]>>j)\
            bits++;\
    }\
    if (bits==RESULT)\
        counter++;\
}

doesn't reset the bits counter for each byte.

To debug the macro, first, write a function you can debug; then, when you're sure it works, convert the function to a macro.

The main problem has been answered by Eric.

The problem with macros is that I can't debug my code.

You could make use of printf's in macro, or you could substitute the macro call with the code segment in the macro.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top