C/C++基础之sizeof使用( 三 )


struct A{  int num1;  int num2;  double num3;};struct B{  int num1;  double num3;  int num2;};结构体A和B中包含的成员都一样 , 只不过顺序不同而已 , 为什么其大小不一样呢?要解释这个问题 , 就要了解结构体成员对齐的规则 。

  • 结构体的大小等于结构体内最大成员大小的整数倍
  • 结构体内的成员的首地址相对于结构体首地址的偏移量是其类型大小的整数倍 , 比如说 double 型成员相对于结构体的首地址的地址偏移量应该是 8 的倍数 。
  • 为了满足规则 1 和 2 编译器会在结构体成员之后进行字节填充!
从三个规则我们来看看为什么 sizeof(B) 等于 24 :首先假设结构体的首地址为0 , 第一个成员 num1 的首地址是 0 (满足规则2) , 它的类型是 int  , 因此它占用地址空间 0——3。第二个成员 num3 是 double 类型 , 它占用 8 个字节 , 由于之前的 num1 只占用了 4 个字节 , 为了满足规则 2  , 需要使用规则 3 在 num1 后面填充 4 个字节(4——7) , 使得 num3 的起始地址偏移量为 8  , 因此 num3 占用的地址空间是:8——15 。第三个成员 num2 是 int 型 , 其大小为 4  , 由于 num1 和num3 一共占用了 16 个字节 , 此时无须任何填充就能满足规则 2 。因此 num2 占用的地址空间是 16——19。那么是不是结构体的总大小就是 0——19 共 20 个字节呢?请注意 , 别忘了规则1!由于结构体内最大成员是 double 占用 8 个字节 , 因此最后还需要在 num2 后面填充 4 个字节 , 使得结构体总体大小为 24。
struct S{ }; sizeof(S); // 结果为1
  • 对于一个空 struct 结构体取 sizeof 运算 , 运算结果为 1 并非 0。因为编译器为保证此空 struct 存在 , 专门分配一个字节 。
  • 如果存在结构体嵌套 , 无论内层还是外层均需要采用内存对齐 。
5 类的 sizeof
  1. 不含继承和 static 成员变量的类 。
在这种情况下 , 只需要考虑对齐方式即可 。
class A {   public:   int b;   float c;   char d; };class B{ };int main(void) {   cout << “sizeof(A) is ” << sizeof(A) << endl;   //输出结果为12  cout << “sizeof(B) is ” << sizeof(B) << endl;   //输出结果为1  return 0 ; }
  • 空的 class 同样也占用 1 个字节 。
  • 计算类对象的大小时 , 类成员函数不占用对象空间 , 只需要考虑类中数据成员的大小 。
  1. 类中存在静态成员变量
class A {   public:   static int a;   int b;   float c;   char d; };int main() {   A object;   cout << “sizeof(object) is ” << sizeof(object) << endl;   //输出结果为12  return 0 ; }因为在程序编译期间 , 就已经为 static 变量在静态存储区域分配了内存空间 , 并且这块内存在程序的整个运行期间都存在 。而每次声明了类 A 的一个对象的时候 , 为该对象在堆上 , 根据对象的大小分配内存 。
  1. 类中包含成员函数
class A {   public:   static int a;   int b;   float c;   char d;   int add(int x,int y)   {     return x+y;   } };int main() {   A object;   cout << “sizeof(object) is ” << sizeof(object) << endl;   b = object.add(3,4);   cout << “sizeof(object) is ” << sizeof(object) << endl;   //输出结果为12  return 0 ; }


推荐阅读