C/C++ 结构体小知识

概要

Struct结构体成员的存放地址以及空间大小

例如:

openAI 的 GPT 大模型的发展历程。

1、结构体成员在内存中的存放顺序

按照C99标准的内容,结构体内的成员是按照成员变量的声明顺序,依次放在内存中

例如:

#include <stdio.h>

typedef struct
{
	char a;
	int b;
	short c;
}s;

int main()
{
   	s s1;
   	printf("s1.a = %p\n", &s1.a);
	printf("s1.b = %p\n", &s1.b);
	printf("s1.c = %p\n", &s1.c);
   
   return 0;
}

那么内存中会依次存放:
字符变量a的地址
整型变量b的地址
短整型变量c的地址

在这里插入图片描述
打印结果如上图所示,通过地址,我们可以看到结构体中变量的存放是依次进行的

2、结构体的大小

结构体的大小是成员类型中最大类型的整数倍

例如:

`typedef struct
{
	char a;
	int b;
	short c;
}s;

对于这个结构体来说,char型占1个字节,int类型占用4个字节,short类型占用2个字节,那么直观来看这个结构体应该总共占用1+4+2=7个字节
但是通过打印这个结构体的大小,我们可以看到运行结果:

printf("sizeof s1= %d\n", sizeof(s1));

在这里插入图片描述
原因有两点:

  1. 结构体内部的成员并不是连续紧挨着存放的
  2. 结构体的大小是成员类型中最大类型的整数倍

所以真正的大小是
4个字节 ✖ 3个变量 = 12个字节

3、存在这个现象的原因?

我们都知道变量的存放应该是,结构体起始地址+偏移量
那这个偏移量应该是多少呢?
我们先说结论:

成员的地址 = 结构体起始地址 + 自身类型长度 * N (N为整数)

还是以上述代码中的结构体为例

#include <stdio.h>
#include <stddef.h>
typedef struct
{
        char a;
        int b;
        short c;
}s;
int main(void)
{
    s s1;
	printf("address s1   = %p \n",&s1);
    printf("address s1.a = %p \n",&s1.a);
	printf("address s1.b = %p \n",&s1.b);
	printf("address s1.c = %p \n",&s1.c);
	return 0;
}


运行结果:
在这里插入图片描述
结构体的起始地址为:0x7fff18e13294
成员a为char型,其前方没有其他数据,所以从结构体的起始地址开始计算,则a的地址应该是:0x7fff18e13294 + 1 * 0
成员b为int型,则地址应为:0x7fff18e13294 + 4 * 1 = 0x7fff18e13298
成员c为short型,则地址应为:0x7fff18e13294 + 2 * 4 = 0x7fff18e1329c

那应该怎么确定N呢?

首先,为了使内存的充分使用,每个成员的地址间距应该在不影响使用前提下尽可能小,所以N也尽可能小

所以这里,我们可以看到a的N取0;b的N最小也可以取0,但是取0的地址0x7fff18e13294 已经被a占用,所以取1;c的地址紧挨着b,应该为0x7fff18e13298 + 4 = 0x7fff18e1329c,这个偏移量8恰好是2的整数倍4,所以满足条件。

所以不同类型变量在结构体中的声明顺序是会对内存产生影响的
例:

typedef struct
{
        char a;
        int b;
        short c;
}s1;
typedef struct
{
        char a;
        short c;
        int b;
}s2;
代码片

打印地址和大小:
在这里插入图片描述
这里交换了short型和int型的声明顺序,可以看到内存占用少了4个字节

这是因为成员的地址是尽可能紧挨着的,所以先声明short型利用上了char型和int型之间的内存浪费。

结论:
1、结构体内的成员按照成员变量的声明顺序,依次存放在内存中;
2、结构体的大小是成员类型中最大类型的整数倍;(本质上是内存对齐,加快寻址的处理速度)
3、每个结构体成员的存放地址都等于结构体起始地址加上自身类型长度的整数倍;
4、想要减少结构体的空间占用,那么最好把数据类型相同的成员或者数据类型大小接近的成员放在一起,尽量避免不同大小的数据类型交错排列

参考文章:浅谈Struct(结构体大小如何确定以及内部成员如何存放)

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值