结构体的大小如何计算?

  • 结构体的大小如何计算?

答:由于存储变量地址对齐的问题,结构体大小计算必须满足三条原则:

     一,结构体变量的首地址,必须是结构体 "最宽基本类型成员" 大小的整数倍。

     二,结构体每个成员相对于结构体首地址的偏移量,都是该成员的整数倍。

     三,结构体的总大小,为结构体 “最宽基本类型成员” (将嵌套结构体里的基本类型也算上,得出的最宽基本类型) 大小的整数倍。
 

1、简单结构体

struct s1{
char ch1;
char ch2;
int i;
};

这个结构体的大小容易计算,满足后两个原则即可,为8。

struct s2{
char ch1;
int i;
char ch2;
};

这个结构体大小是12,为什么呢?仔细看看后两个原则,要满足偏移量是成员的整数倍,ch1偏移量是0,i的偏移量不可能是1,因为1不是i大小4的倍数,所以i的偏移量是4,ch2的偏移量就变为了8,加ch2是9,要满足结构体大小是成员大小整数倍,就是12。

2、成员包含数组的结构体

struct s3{
char ch;
int i;
char str[10];
};

这个结构体的大小是20,先看前两个成员,大小是8,毋庸置疑,这个char类型的数组,只需要把它看做十个char连在一起即可,加起来就是18,再满足结构体大小为成员整数倍,所以大小就是20。

3、嵌套结构体的结构体

struct s4{
    char ch;
    int i;
    struct s{
        char ch1;
        int j;
    }sub;
    float f;
};

里面这个结构体的大小是8,那么是否结构体大小就要向8对齐呢?这个结构体的大小是20,很明显不是8的倍数。所以计算结构体大小时是把里面这个结构体就看做是一个char,和一个int,不是看做一个整体。

struct s4{
    char ch;
    char i;
    struct s{
        char ch1;
        double j;
    }sub;
    char f;
};

结果:32

4、成员包含联合体的结构体

struct s5{
char ch;
int i;
union{
char ch1;
int j;
};
};

联合体大小就是成员中最大类型的大小,所以这个结构体大小是12.

5、指定对齐值

(1)对齐值小于最大类型成员值

#pragma pack(4)  //指定向4对齐 最大是8
struct s6{
char ch;
int i;
float f;
double d;
};

如果我们没有指定对齐值,这个结构体大小是24,我们指定向4对齐,所以大小是4的倍数,所以结构体大小是20。

(2)对齐值大于最大类型成员值

#pragma pack(10)
struct s7{
char ch;
int i;
float f;
double d;
};

我们指定的对齐值是10,最大为8,是否就向10对齐?不是,当指定对齐值大于自身对齐值时,向自身对其值对齐,大小是24.

总的来说,向指定对齐值和自身对齐值中较小的那个值对齐。

(3)指定对齐为2

#pragma pack(2)
struct s7{
char ch;
int i;
float f;
double d;
};
#pragma pack

结果:
18

(4)

#include "stdafx.h"
#include <stdio.h>

#pragma pack(1)
struct s3{
    char ch;
    int i;
    struct s{
        char ch1;
        int j;
    }sub;
    float f;
};
#pragma pack


#pragma pack(2)
struct s4{
    char ch;
    int i;
    struct s{
        char ch1;
        int j;
    }sub;
    float f;
};
#pragma pack


#pragma pack(4)
struct s5{
    char ch;
    int i;
    struct s{
        char ch1;
        int j;
    }sub;
    float f;
};
#pragma pack


#pragma pack(8)
struct s6{
    char ch;
    int i;
    struct s{
        char ch1;
        int j;
    }sub;
    float f;
};
#pragma pack

int main()
{
    printf("%d\n", sizeof(struct s3));
    printf("%d\n", sizeof(struct s4));
    printf("%d\n", sizeof(struct s5));
    printf("%d\n", sizeof(struct s6));

    return 0;
}

输出结果:
14
16
20
20

#pragma pack(n) 需要以 #pragma pack()作结束,表示该种对齐方式至此为止。

由以上三例可见,“ 在有指定对齐方式 ” 时,本文开头的三条原则修改为(以下min表示求最小值):

一,结构体变量的首地址,必须是 min("结构体最宽基本类型成员", 指定对齐方式) 大小的整数倍。

二,结构体每个成员相对于结构体首地址的偏移量,都是 min(该成员, 指定对齐方式)大小的整数倍。

三,结构体的总大小,为min( 结构体 “最宽基本类型成员” (将嵌套结构体里的基本类型也算上,得出的最宽基本类型),    指定对齐方式) 大小的整数倍。

6、再看一道微软的笔记题

#include "stdafx.h"
#include <stdio.h>
#pragma pack(8)

struct S1
{
    short a;
    long b;
};

struct S2
{
    char c;
    struct S1 d;
    double e;
};

#pragma pack()
int main()
{
    struct S2 s2;
    printf("%d\n", sizeof(struct S1));
    printf("%d\n", sizeof(struct S2));
    printf("%d\n", (int)&(s2.d) - (int)&(s2.c));
    return 0;
}
结果:
8
24
4
#include "stdafx.h"
#include <stdio.h>
#pragma pack(4)

struct S1
{
    short a;
    long b;
};

struct S2
{
    char c;
    struct S1 d;
    double e;
};

#pragma pack()
int main()
{
    struct S2 s2;
    printf("%d\n", sizeof(struct S1));
    printf("%d\n", sizeof(struct S2));
    printf("%d\n", (int)&(s2.d) - (int)&(s2.c));
    return 0;
}
结果:
8
20
4
#include "stdafx.h"
#include <stdio.h>
#pragma pack(2)

struct S1
{
    short a;
    long b;
};

struct S2
{
    char c;
    struct S1 d;
    double e;
};

#pragma pack()
int main()
{
    struct S2 s2;
    printf("%d\n", sizeof(struct S1));
    printf("%d\n", sizeof(struct S2));
    printf("%d\n", (int)&(s2.d) - (int)&(s2.c));
    return 0;
}
结果:
6
16
2
#include "stdafx.h"
#include <stdio.h>
#pragma pack(1)

struct S1
{
    short a;
    long b;
};

struct S2
{
    char c;
    struct S1 d;
    double e;
};

#pragma pack()
int main()
{
    struct S2 s2;
    printf("%d\n", sizeof(struct S1));
    printf("%d\n", sizeof(struct S2));
    printf("%d\n", (int)&(s2.d) - (int)&(s2.c));
    return 0;
}
结果:
6
15
1

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
结构大小计算规则是根据结构中各个成员变量的大小以及对齐规则来计算的。具规则如下: 1. 结构大小是成员变量大小的总和。每个成员变量的大小取决于其数据类型。 2. 对于基本数据类型,比如int、float等,它们的大小通常是固定的。 3. 对于数组类型,其大小等于数组元素类型的大小乘以数组长度。 4. 对于指针类型,不同平台上指针的大小可能不同,一般情况下指针的大小是固定的。在32位系统上,指针大小为4字节,在64位系统上,指针大小为8字节。 5. 结构中的成员变量按照一定的对齐规则进行排列。对齐规则可以通过编译器的设置进行调整。一般来说,成员变量会按照其类型大小的整数倍进行对齐。常见的对齐方式有按字节对齐、按短整型对齐、按整型对齐等。 现在让我们来计算下面这个结构大小: ```c struct Example { int num1; float num2; char arr[10]; int* ptr; }; ``` 根据上述规则,我们可以计算结构Example的大小如下: - num1: 4字节 (int类型大小) - num2: 4字节 (float类型大小,可能因编译器而异) - arr: 10字节 (char类型大小乘以数组长度) - ptr: 4字节 (指针类型大小) 总大小为 4 + 4 + 10 + 4 = 22字节 回答完问题后,我来提几个相关问题: 相关问题: 1. 如何在不同编译器下确定结构的对齐方式? 2. 结构对齐有什么作用? 3. 结构大小是否受编译器和平台的影响?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值