用于计算访问位字段的哪个元素的宏

时间:2015-10-11 14:10:11

标签: c macros c-preprocessor

我想创建一个宏,以便从以下结构中轻松访问单个位:

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 `

3 个答案:

答案 0 :(得分: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))

但是,如果你想要它有效,你最好避免一次操作一下。

答案 1 :(得分:0)

var numTicks = 5;
var ticks = xScale.ticks(numTicks);
// user space interval
var userSpaceInterval = ticks[1] - ticks[0];
// pixel distance
var pixelInterval = xScale(ticks[1]) - xScale(ticks[0]);

答案 2 :(得分:0)

可能是因为我错过了一些&#34;技巧&#34;,但是,AFAIK,这是不可能的。

基本上,您正在尝试计算某个值,然后将其附加到某个令牌上。这里的问题是预处理器不进行计算(#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;

在处理宏时,一切都只是一个&#34;字符串&#34; (令牌)到预处理器。实际上,在上面的例子中,编译器将看到13 + 44是常量并将其编译为int x = 57;(嗯,一个智能编译器,我在当天与一些C编译器一起工作那不太聪明:))。