2015-10-11 38 views
0

我想創建一個宏來得到一個結構類似下面的輕鬆訪問單個位:宏來計算位字段的哪一個元素被訪問

typedef union 
{ 
    struct 
    { 
     uint8_t bit0 : 1; 
     uint8_t bit1 : 1; 
     uint8_t bit2 : 1; 
     uint8_t bit3 : 1; 
     uint8_t bit4 : 1; 
     uint8_t bit5 : 1; 
     uint8_t bit6 : 1; 
     uint8_t bit7 : 1; 
    }; 
    uint8_t raw; 
} Bitfield; 

我有一個兩維數組(x)這個結構。我可以做的最好的是:

#define xstr(r,c,b) str(r,c,b) 
#define str(r,c,b) (x[r][c].bit##b) 
#define getBit(bitCollum,row)(xstr(row,(bitCollum/8),(bitCollum%8)) 

當我嘗試使用像uint8_t a = getBit(15,2);宏將擴大到

uint8_t a = ((img [ 2 ] [ (15/8) ] . bit 15 % 8)); 

,我希望創建一個將擴大到結構:

uint8_t a = ((img [ 2 ] [ (15/8) ] . bit7)); 

這甚至有可能嗎?

bitCollumrow永遠是字面上的整數;表達式不會在循環或類似的東西中運行。

編輯:

看到這是不可能的我看着一個簡單的增量的拆卸和我看到了不同的指令,但對於我吃驚的是屏蔽了快後。

` x.raw = 0b10101001; 
00000040 LDI R24,0xA9  Load immediate 
00000041 STD Y+8,R24  Store indirect with displacement 
    uint8_t y = 0b10101001; 
00000042 LDI R24,0xA9  Load immediate 
00000043 STD Y+1,R24  Store indirect with displacement 
    uint16_t xSum=0; 
00000044 STD Y+3,R1  Store indirect with displacement 
00000045 STD Y+2,R1  Store indirect with displacement 
    uint16_t ySum=0; 
00000046 STD Y+5,R1  Store indirect with displacement 
00000047 STD Y+4,R1  Store indirect with displacement 
    xSum+=x.bit3; 
00000048 LDD R24,Y+8  Load indirect with displacement 
00000049 BST R24,3  Bit store from register to T 
0000004A CLR R24  Clear Register 
0000004B BLD R24,0  Bit load from T to register 
0000004C MOV R24,R24  Copy register 
0000004D LDI R25,0x00  Load immediate 
0000004E LDD R18,Y+2  Load indirect with displacement 
0000004F LDD R19,Y+3  Load indirect with displacement 
00000050 ADD R24,R18  Add without carry 
00000051 ADC R25,R19  Add with carry 
00000052 STD Y+3,R25  Store indirect with displacement 
00000053 STD Y+2,R24  Store indirect with displacement 
    ySum+=y&0b00010000; 
00000054 LDD R24,Y+1  Load indirect with displacement 
00000055 MOV R24,R24  Copy register 
00000056 LDI R25,0x00  Load immediate 
00000057 ANDI R24,0x10  Logical AND with immediate 
00000058 CLR R25  Clear Register 
00000059 LDD R18,Y+4  Load indirect with displacement 
0000005A LDD R19,Y+5  Load indirect with displacement 
0000005B ADD R24,R18  Add without carry 
0000005C ADC R25,R19  Add with carry 
0000005D STD Y+5,R25  Store indirect with displacement 
0000005E STD Y+4,R24  Store indirect with displacement ` 
+0

你爲什麼不使用&運算符。例如:'result = variable&(0x01000000)' –

+0

它不會像那樣工作......您需要對帶'.raw'成員的位操作進行計算移位並屏蔽ops。並且擔心通過位域訪問字節內位的佈局。 C標準留下了編譯器自行決定的位數。編譯器遵循平臺上的ABI,但通常在可移植性方面存在問題。 –

+0

我想寫一個儘可能少的指令的應用程序,所以我想使用定義爲我生成的代碼,而不是使用for循環例如 – alex529

回答

0

這可能是因爲我錯過了一些「貓膩」,但是,據我所知,這是不可能的。

基本上,你要計算的值,然後將其追加到一些象徵性的。這裏的問題是預處理器不會進行計算(除了#if和其他語句)。因此,舉例來說:

#define X2(A,B) A##B 
#define X(A,B) X2(A,B) 

int x = X(13 + 4, 4); 

這將擴大到:

int x = 13 + 44; 

到:

int x = 174; 

如果你試圖把括號,你只會得到編譯器錯誤,因爲這是無效的:

int x = (13+4)4; 

處理宏時,所有內容都只是預處理器的「字符串」(令牌)。實際上,在上面的例子中,編譯器會看到13 + 44是恆定的,並將其編譯爲int x = 57;(嗯,這是一個智能編譯器,我在一天中使用過一些並不那麼聰明的C編譯器: ))。

0
#define GET_BIT(VAR8,IDX) ((VAR8>>IDX) & 1) 


int main(void){ 
    unsigned char c=3; 
    int i; 
    printf("Bits of char %d: ",c); 
    for(i=0; i<8;i++){ 
     printf("%d ",GET_BIT(c,i)); 
    } 
    printf("\n"); 
    return 0; 
} 
+0

這個問題確實觀察到宏只能使用文字來表示位數。 –

+0

我演示瞭如何在char(BYTE)中單獨訪問(讀取)任何位而無需訪問結構字段。 @PineForestRanch爲這個問題提供了一個完整的宏。 – milevyo

3

取而代之的是結構的,使用簡單的字節 - uint8_t

#define GETBIT(r,c) (img[r][(c) >> 3] & (1 << ((c) & 7))) 
#define SETBIT(r,c) img[r][(c) >> 3] |= (1 << ((c) & 7)) 
#define CLRBIT(r,c) img[r][(c) >> 3] &= ~(1 << ((c) & 7)) 

但是,如果你想有效的,你最好避免在同一時間操作的事情之一位。