문제

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.

도움이 되었습니까?

해결책 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.

다른 팁

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top