2014-02-18 60 views
1

我的任務是編寫一個宏,它檢查INT數組中有多少個元素激起5個位已打開。一個宏來計算位(設置)

我知道一個宏是一個非常冒險的做法,但這是一些考試中出現的問題。

這是我的代碼:

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


} 

與宏的問題是,我不能調試我的代碼。我幾次沒有成功,但我意識到我得到的結果是1而不是2.

計數器變量是計算有多少元素有5位的計數器變量。位變量在某個元素中計數了多少位。

謝謝你的幫助。

+0

賦值**是否要求**使用宏來計數位和/或測試數組中的元素? (這是一個非常糟糕的主意。) –

+0

如果你在POSIX平臺上,你可以嘗試使用clang作爲編譯器。它能夠非常有效地將語句的起源追溯到宏定義。 –

+0

@EricPostpischil是的,該任務需要兩者。我贊同你。 – Alan

回答

2

宏在計數每個數組元素中的位之前未能將bits設置爲零。它僅在整個陣列上的循環之前將bits設置爲零。

+0

謝謝。這確實是個問題。 – Alan

1

我說

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

是錯誤的,因爲它測試,如果結果中的任何位被置位,如果沒有他們的所有 設置。我已經重寫了代碼來計數的位數1 字節

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

注意,如果面膜是無符號或有超過8位這隻適用,因此char不會>做(你int雖然可以)。

但這是錯誤的。

然而,

#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++;\ 
} 

不重置的比特對每個字節計數器。

要調試宏,首先編寫一個可調試的函數;那麼,當你確定它有效時,將該函數轉換爲一個宏。

+0

我想說的是一樣的。編寫函數,您可以調試,然後在修復所有錯誤之後,將其替換爲宏定義。 – likern

+0

在'mask&arr [i] >> j'中,'>>'在'&'之前綁定,所以這會移動'arr [i]',然後執行'&'。 '掩碼'有一個位的設置,所以結果是一個單一位的測試,而不是任何位。 –

+0

@Guntram Blohm我每次都要測試RIGHTEST位。如果我的號碼是00001100,那麼如果j是2,我將這兩個位移動兩次,即我測試掩碼與00000011並設置最後一位(1),因此我將位變量加1。謝謝你的回答,但我仍然不明白爲什麼我的方式是錯誤的,除了宏觀是一個壞主意。 – Alan

6

我可能會做這樣的事情,如果你真的想要一個宏:

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

定義BITS_PER_U64應該是一個明顯的擴展,如果它的需要。

但是,這樣做的一個小的內聯函數會被很多更安全,更好的解決方案...

還有this,這對方式來獲得以各種方式「人口數」一整節...

0

Eric的主要問題已得到解答。

宏的問題是我無法調試我的代碼。

您可以在宏中使用printf,或者您可以將宏調用替換爲宏中的代碼段。