C语言结构体大小尺寸

 1.字节对齐

      每一款不同的处理器,存取内存数据都会有不同的策略,如果是 32 位的 CPU,一般
来讲他在存取内存数据的时候,每次至少存取 4 个字节(即 32 位),也就是按 4 字节对齐
来存取的。换个角度讲:CPU 有这个能力,他能一次存取 4 个字节。
接下来我们可以想到,为了更高效地读取数据,编译器会尽可能地将变量塞进一个 4
字节单元里面,因为这样最省时间。如果变量比较大,4 个字节放不下,则编译器会尽可能
地将变量塞进两个 4 字节单元里面,反正一句话:两个坑能装得下的就绝不用三个坑。这
就是为什么变量的地址要对齐的最根本原因。

所谓地址对齐主要思想:
尽可能提高CPU的运行效率(仅能能的少取读取/写入内存)一个数据如能使用一个单元来存放感觉对不使用两个, 两个能放绝对不用三个

2.普通变量的M值

概念: 一个数据它的大小是固定的(比如整型),如果这个数据他所存放的地址能够被某一个数
所整除(4)那么这个数就成为当前数据的M值。
可以根据具体的系统字长以及数据的大小可以计算得出M值。

int a;   // a占用 4 字节, 如果a存放在能被4整除的地址下则是地址对齐, 因此他的M值为4
char b;  // b占用 1 字节, 如果b存放在能被1整除的地址下则是地址对齐, 因此他的M值为1
short c; // c占用 2 字节, 如果c存放在能被2整除的地址下则是地址对齐, 因此他的M值为2
double d;// d占用 8 字节, 如果d存放在能被4整除的地址下则是地址对齐, 因此他的M值为4
float e; // e占用 4 字节, 如果e存放在能被4整除的地址下则是地址对齐, 因此他的M值为4

地址分析
a:010FF7E4
b:010FF7DB
c:010FF7CC
d:010FF7BC
e:010FF7B0

注意:如果一个变量的大小超过8 (8/16/32) M值则按8计算即可

3.结构体的M值

结构体的M值
结构体中有多个成员,取决于成员中M值最大的成员。
结构体的地址,必须能被结构体的M值整除(第一个成员的首地址为0)
结构体的尺寸,等于成员中宽度最宽成员的倍数

4.实例分析

#include<stdio.h>

struct student {
	int a;
	char b;
	float c;
	double d;
	short e;
};

int main() {
	struct student std ;
	printf("%d\n", sizeof(std));
	printf("a:%p\n", &std.a);
	printf("b:%p\n", &std.b);
	printf("c:%p\n", &std.c);
	printf("d:%p\n", &std.d);
	printf("e:%p\n", &std.e);
	return 0;
}
运行结果:
32
a:0X00B9FC10
b:0X00B9FC14
c:0X00B9FC18
d:0X00B9FC20
e:0X00B9FC28

为什么会出现这样的结果呢我们来分析一下:(1)首先结构体成员最大的M值为8,所以第一个成员a分到8个字节自身需要4个字节剩余4个字节第一个成员的首地址为0现在排列到地址为3的空间(2)第二个结构体成员b自身M值为1现在的地址为4可以整除M故可以接着排列(3)第三个结体成员c自身M值为4当地址为8的时候才可以整除M故地址5 6 7空余(4)第四个结构体成员d的M值为8当地址为16的时候才可以整除M故地址空余12 13 14 15(5)第五个结体成员e的M值为2当地址为24的时候才可以整除M(6)最后的结果要是结构体成员最大的M值的整数倍

 让我们在练习一下

struct student {
    int a;
    char b;
    short e;
    float c;
    double d;
};

 答案为24  这个结构体大小你分析对了吗?是不是很简单了其实第三个结构体成员的M值为2地址为6 7就可以放这个成员了

5.总结

结构体大小需要考虑:
(1)自身对齐(就是数据类型所占的字节也是普通变量的M值)
(2)默认对齐(系统字长 32位:4字节   64位:8字节)
(3)有效对齐(自身对齐和默认对齐的最小值)
(4)地址对齐(一定要整除有效地址)

 struct stu1
{
    char a;
    int b;
    char c;
    char d;
};//结果为12

/*  char a  自身对齐:1     默认对齐:8  有效对齐:1        地址 0

     int b  自身对齐:4     默认对齐:8  有效对齐:4        地址 4  5  6 7

     char c  自身对齐:1     默认对齐:8  有效对齐:1        地址 8

     char d  自身对齐:1     默认对齐:8  有效对齐:1        地址 9

     最后的地址要能整除有效地址,显然10不能整除4,故需要补地址10 11

     最终占12个字节 */


struct stu2
{
    char a;
    short b;
    char c;
    char d;
};//结果为6

/*  char a  自身对齐:1     默认对齐:8  有效对齐:1        地址 0

     short b  自身对齐:2     默认对齐:8  有效对齐:2        地址 2  3 

     char c  自身对齐:1     默认对齐:8  有效对齐:1        地址 4

     char d  自身对齐:1     默认对齐:8  有效对齐:1        地址 5

     最后的地址可以整除有效地址,最终占6个字节 */

struct stu3
{
    char a;
    double b;
    char c;
    char d;
};//结果为24

/*  char a  自身对齐:1     默认对齐:8  有效对齐:1        地址 0

     double b  自身对齐:8     默认对齐:8  有效对齐:8        地址 8-15

     char c  自身对齐:1     默认对齐:8  有效对齐:1        地址 16

     char d  自身对齐:1     默认对齐:8  有效对齐:1        地址 17

     最后的地址要能整除有效地址,显然18不能整除8,

    故需要补地址18-23,最终占24个字节 */

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

本环

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值