2013-01-07 219 views
7
#include <stdint.h> 
#include <stdio.h> 

typedef union { 
    uint64_t u[2]; 
    struct { 
     uint64_t a:30; 
     uint64_t b:30; 
     uint64_t c:30; 
     uint64_t d:30; 
     uint64_t e:8; 
    }x; 
} mystruct; 

int main() 
{ 
    printf("Size %d\n", sizeof(mystruct)); 
} 

我想在64位机器上编译它。预期的输出是16,但我越来越24. 我知道一些对齐发生在这里,但我不知道为什么,因为结构x是正好16个字节。 有人可以解释这一点。 感谢sizeof没有显示预期的输出

+2

您正在使用位字段:K&R第150页:*”几乎所有关于位域的东西都是依赖于实现的“*”。我个人会忽略“几乎”。 – cdarke

+2

@cd他们说*几乎*因为其余未指定;) – ouah

回答

6

从C标准:

(C99,6.7.2.1p10)“[...]如果没有足够的空间仍然存在, 是否不适合一个位域放入下一个单元或重叠的相邻单元是 实现定义的。“

因此,在你执行不重叠:ab成员都在一个单元,cd在另一个单元和e是另一个单位:8 + 8 + 8 = 24

6

对于64位机,字段ab使用在结构中的第一个64位值的60个比特,cd使用在结构中的下一个64位值的60位值,并将因为e是8位,它不适合从该64位值剩余的4位,因此需要另一个64位值。因此8×3 = 24个字节。

3

位字段的元素将永远不会重叠两个内存单元(在您的情况下内存单元是64位元素)。

旁边的事实是位域的实现都依赖于编译器,还有就是你的位域的结构实际上是存储在内存中通过以下方式一切机会:

struct { 
    uint64_t a:30; 
    uint64_t b:30; 
    uint64_t :4; 
    uint64_t c:30; 
    uint64_t d:30; 
    uint64_t :4; 
    uint64_t e:8; 
    uint64_t :56; 
}x;