使用不同的编译器打包结构大小和继承

时间:2017-02-28 06:40:27

标签: c++ gcc visual-studio-2013 packing

考虑一个MWE:

public class AndroidSmackInitializer implements SmackInitializer {

    @Override
    public List<Exception> initialize() {
        SmackConfiguration.setDefaultHostnameVerifier(new StrictHostnameVerifier());
        Base64.setEncoder(AndroidBase64Encoder.getInstance());
        Base64UrlSafeEncoder.setEncoder(AndroidBase64UrlSafeEncoder.getInstance());
        return null;
    }

} 

在Linux上我尝试编译并运行:

#include <iostream>

struct A     {}         __attribute__((packed)) ;
struct B : A { int x; } __attribute__((packed)) ;

struct C : A { B y; }   __attribute__((packed)) ;

int main () {
    std::cout << "Size of A: " << sizeof(A) << std::endl;
    std::cout << "Size of B: " << sizeof(B) << std::endl;
    std::cout << "Size of C: " << sizeof(C) << std::endl;
};

A和B一切都很清楚。但是C怎么样?是什么在C&C的大小上加1个字节?此外,如果您要删除任何继承关系,无论是B还是C,C的大小为4.使用MS编译器(至少是VS 2013附带的一个),我得到了1,4和4个大小。任何解释和细节都表示赞赏。

1 个答案:

答案 0 :(得分:2)

  

[class.derived] / 7(标准草案)

     

...基类子对象可以是零大小(Clause [class]);但是,必须不在同一地址([expr.eq])分配具有相同类类型且属于同一最多派生对象的两个子对象。 - 结束说明]

C的子对象B::A(成员基数y)和C::A(直接基数)都属于A类型。 y可能与C的空基地位于同一地址,但由于它也有相同类型的基数,B的基数可能不具有相同的地址,因此必须用填充来抵消。 GCC遵循此规则,仅将打包请求应用于正确对齐所需的填充。