考虑一个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个大小。任何解释和细节都表示赞赏。
答案 0 :(得分:2)
[class.derived] / 7(标准草案)
...基类子对象可以是零大小(Clause [class]);但是,必须不在同一地址([expr.eq])分配具有相同类类型且属于同一最多派生对象的两个子对象。 - 结束说明]
C
的子对象B::A
(成员基数y
)和C::A
(直接基数)都属于A
类型。 y
可能与C
的空基地位于同一地址,但由于它也有相同类型的基数,B
的基数可能不具有相同的地址,因此必须用填充来抵消。 GCC遵循此规则,仅将打包请求应用于正确对齐所需的填充。