首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >联合内的位域对齐方式

联合内的位域对齐方式
EN

Stack Overflow用户
提问于 2012-09-12 16:05:20
回答 3查看 2K关注 0票数 4

我对以下代码是如何在内存中布局的感到有点困惑:

代码语言:javascript
复制
struct Thing
{
    union
    {
        unsigned value:24;
        uint8_t bytes[3];
    };
    Thing(int v)
            :value(v)
    {}

    void foo()
    {
        printf("Thing %p value=%d !\n", this, value);
    }

} __attribute__((__packed__));

在Linux3.3、4.3或4.6上(没有我能想到的任何特殊选项-只有4.6上的"-Wall -g“),结构的大小始终是4:

代码语言:javascript
复制
$ pahole ./union
struct Thing {
        union {
                unsigned int               value;                /*           4 */
                unsigned char              bytes[3];             /*           3 */
        };
[...]

我们在这里有一些类似的代码,其中我们有一个结构中的无符号值:24,有人添加了联合,并无意中将结构的大小从3字节增加到4字节。如果我试图将联合定义为“压缩的”--大小仍然是4,也会发生同样的事情。这种行为是否符合C++规范?解释是什么呢?

后来的编辑:将"C spec“替换为"C++ spec”。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-12 16:39:53

你错过了匿名联盟的打包属性。考虑这个例子:

代码语言:javascript
复制
#define PACKED __attribute__((__packed__))
struct S1 { unsigned value:24; } PACKED ;
struct S2 { union { char a[3]; unsigned value:24; };  } PACKED ;
struct S3 { union { char a[3]; unsigned value:24; } PACKED ;  };


int main() {
   std::cout << sizeof(S1) << std::endl;
   std::cout << sizeof(S2) << std::endl;
   std::cout << sizeof(S3) << std::endl;
}

输出:

代码语言:javascript
复制
3
4
3

packed属性有点奇怪,我总是尝试测试每种可能的组合以获得正确的结果。

票数 1
EN

Stack Overflow用户

发布于 2012-09-12 16:44:08

好吧,首先,__attribute__((__packed__))是一个gcc的扩展,所以标准没有任何东西来说明可能会发生什么,或者可能不会发生什么。

然而,一般而言,编译器被允许在位字段之间插入它认为合适的任何填充。具体地说,我见过这样的编译器:

代码语言:javascript
复制
 struct
 {
     short a : 8;
     int b : 8;
 }

将在32位边界上对齐b。

基本上,如果使用位域,就只能靠自己了。不能保证字段的顺序或填充。唯一的保证就是位字段的大小。

票数 0
EN

Stack Overflow用户

发布于 2012-09-12 16:47:49

这个问题被标记为C++,但您提到了C规范。在这一点上,C和C++是有区别的。在C中,位字段只能是整数类型,而C++允许任何整数类型。

由于位域映射为整数类型,因此我希望位域的大小始终为1、2或4。

因此,这将为您提供sizeof 3:

代码语言:javascript
复制
struct Thing
{
    union
    {
        // without 'short' int would be assumed -> 4 bytes
        unsigned short value:15; // -> maps to short -> 2 bytes
        uint8_t bytes[3];        // -> 3 bytes, so the whole union is 3 bytes long
    };
}

对于value:24,它将始终映射到最近的整数类型,即整数。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12383708

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档