以下bit field
示例代码来自here。它声称存储效率更高。但我想知道编译器如何处理位字段?
我猜C编译器 HAS TO 会为按位操作生成额外的指令。因此,尽管数据大小减小,但代码大小也会增加。
任何熟悉C编译器的人都可以解释一下吗?
#include <stdio.h>
// A space optimized representation of date
struct date
{
// d has value between 1 and 31, so 5 bits
// are sufficient
unsigned int d: 5;
// m has value between 1 and 12, so 4 bits
// are sufficient
unsigned int m: 4;
unsigned int y;
};
int main()
{
printf("Size of date is %d bytes\n", sizeof(struct date));
struct date dt = {31, 12, 2014};
printf("Date is %d/%d/%d", dt.d, dt.m, dt.y);
return 0;
}
答案 0 :(得分:5)
因此,尽管数据大小减小,但代码大小也会增加。
一般来说,这是正确的:它是在更紧凑的存储与更快的访问之间的权衡。
例如,这是我的编译器为您的位域示例中的printf
语句生成的内容:
movq _dt@GOTPCREL(%rip), %rax
movzwl (%rax), %edx
movl %edx, %esi
andl $31, %esi ; -- extract the 5 bits representing day
shrl $5, %edx ; -+ extract the four bits for the month
andl $15, %edx ; /
movl 4(%rax), %ecx ; -- year doesn't require any bit manipulation
leaq L_.str.1(%rip), %rdi
xorl %eax, %eax
callq _printf
为了进行比较,date
为简单struct
时的相同代码:
movq _dt@GOTPCREL(%rip), %rax
movl (%rax), %esi ; -- day
movl 4(%rax), %edx ; -- month
movl 8(%rax), %ecx ; -- year
leaq L_.str.1(%rip), %rdi
xorl %eax, %eax
callq _printf
所有这些当然都是编译器和平台特定的。
答案 1 :(得分:2)
我记得,位字段的文档说这只是一个 建议编译器。实施是免费的 选择实际位或一些效率较低(空间)的实现。
比特字段实际上只是处理比特的一种方便的语法。
但事实证明,嵌入式编译器倾向于使用真正的位字段
因为使用位是嵌入式编程中非常常见的任务。
当然,如果需要,这必须与编译器一起记录
使用此功能。
关于汇编程序的复杂性,真正的位有意义 需要来自汇编程序的更多工作。