我实施了这个解决方案[1]
#include <stdio.h>
#define bitoffsetof(t, f) \
({ union { unsigned long long raw; t typ; }; \
raw = 0; ++typ.f; __builtin_ctzll(raw); })
#define bitsizeof(t, f) \
({ union { unsigned long long raw; t typ; }; \
raw = 0; --typ.f; 8*sizeof(raw)-__builtin_clzll(raw)\
-__builtin_ctzll(raw); })
struct RGB565 { unsigned short r:5, g:6, b:5; };
int main()
{
printf("offset(width): r=%d(%d) g=%d(%d) b=%d(%d)\n",
bitoffsetof(RGB565, r), bitsizeof(RGB565, r),
bitoffsetof(RGB565, g), bitsizeof(RGB565, g),
bitoffsetof(RGB565, b), bitsizeof(RGB565, b));
}
$ gcc bitfieldtest.cpp && ./a.out
offset(width): r=0(5) g=5(6) b=11(5)
[1] https://twitter.com/suarezvictor/status/1477697986243272706
更新:我确认这是在编译时解决的:
void fill(int *x)
{
x[0]=bitoffsetof(RGB565, r);
x[1]=bitsizeof(RGB565, r);
x[2]=bitoffsetof(RGB565, g);
x[3]=bitsizeof(RGB565, g);
x[4]=bitoffsetof(RGB565, b);
x[5]=bitsizeof(RGB565, b);
}
汇编器输出:
fill:
.LFB12:
.cfi_startproc
movl $0, (%rdi)
movl $5, 4(%rdi)
movl $5, 8(%rdi)
movl $6, 12(%rdi)
movl $11, 16(%rdi)
movl $5, 20(%rdi)
ret