计算访问位域的哪个元素的宏
Macro to compute which element of a bit field is accessed
我想创建一个宏来从如下结构中轻松访问单个位:
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 ) );
这可能吗?
bitCollum
和 row
将始终是字面整数;表达式不会 运行 在循环或类似的东西中。
编辑:
在看到这是不可能的之后,我查看了一个简单增量的反汇编,我看到了不同的指令,但令我惊讶的是,屏蔽速度更快。
` 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 `
#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;
}
使用简单的字节而不是结构 - 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))
但是,如果您希望它高效,最好避免一次一位地进行操作。
可能是我遗漏了一些 "trick",但是,据我所知,这是不可能的。
基本上,您正在尝试计算一个值,然后将其附加到某个标记。这里的问题是预处理器不进行计算(#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;
在处理宏时,一切都只是预处理器的 "string"(标记)。实际上,在上面的示例中,编译器会看到 13 + 44 是常量并将其编译为 int x = 57;
(好吧,一个智能编译器,我以前使用过一些 C 编译器,它们是不太聪明 :)).
我想创建一个宏来从如下结构中轻松访问单个位:
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 ) );
这可能吗?
bitCollum
和 row
将始终是字面整数;表达式不会 运行 在循环或类似的东西中。
编辑:
在看到这是不可能的之后,我查看了一个简单增量的反汇编,我看到了不同的指令,但令我惊讶的是,屏蔽速度更快。
` 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 `
#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;
}
使用简单的字节而不是结构 - 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))
但是,如果您希望它高效,最好避免一次一位地进行操作。
可能是我遗漏了一些 "trick",但是,据我所知,这是不可能的。
基本上,您正在尝试计算一个值,然后将其附加到某个标记。这里的问题是预处理器不进行计算(#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;
在处理宏时,一切都只是预处理器的 "string"(标记)。实际上,在上面的示例中,编译器会看到 13 + 44 是常量并将其编译为 int x = 57;
(好吧,一个智能编译器,我以前使用过一些 C 编译器,它们是不太聪明 :)).