C编译器如何处理位域?

How does C compiler handle bit-field?

以下bit field示例代码来自here。它声称具有更好的存储效率。但是我想知道编译器是如何处理位域的?

我想 C 编译器必须 生成额外的位操作指令。所以虽然数据量减少了,代码量却增加了。

任何熟悉 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;
} 

So although the data size is reduced, the code size is increased.

总的来说,这是正确的:这是更紧凑的存储与更快的访问之间的权衡。

例如,这是我的编译器为您的位域示例中的 printf 语句生成的内容:

    movq    _dt@GOTPCREL(%rip), %rax
    movzwl  (%rax), %edx
    movl    %edx, %esi
    andl    , %esi     ; -- extract the 5 bits representing day
    shrl    , %edx      ; -+ extract the four bits for the month
    andl    , %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

当然,所有这些都是特定于编译器和平台的。

我记得,位字段的文档说这只是一个
编译器的建议。实施是免费的
选择实际位或一些效率较低的(space-wise)实现。

位域实际上只是一种用于处理位的便利语法。

但事实证明嵌入式编译器倾向于使用真实的位域,
因为使用位是嵌入式编程中非常常见的任务。
当然,如果需要的话,必须用编译器记录这一点
使用此功能。

关于汇编程序的复杂性,真正的位
是有道理的 需要汇编器做更多的工作。