前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据结构类型(内存篇)

数据结构类型(内存篇)

作者头像
木杉乀
发布2021-04-02 06:35:23
5160
发布2021-04-02 06:35:23
举报
文章被收录于专栏:木杉の小屋木杉の小屋

数据结构类型(内存篇)超全结构体,联合,枚举内存解释(适用c语言入门)

一.结构体的内存

内存对齐

规则:

1.结构体的第一个数据成员存放的地址为结构体变量偏移量为 0 的地址处.

2.其他起始地址为该类型变量所占内存的整数倍,如果不足部分用数据填充到所占内存的整数倍

3.结构体所占总内存为该结构体的成员中基本数据类型占字节数最大的整数倍

(见图解1-1)

代码语言:javascript
复制
#include

struct str1 {   // ??
	char a;     //  1 byte  //此处若删除char a 则所占内存为 24 以验证规则 1;(自行验证)
	int b;      //  4 byte
	float c;    //  4 byte
	double d;   //  8 byte(最大)
	char ch;    //  1 byte
}s1;            // 32 byte

//将结构体内部变量调换位置后结构体内存占用发生改变

struct str2 {   // ?? 
	char a;     //  1 byte
	char ch;    //  1 byte
	int b;      //  4 byte
	float c;    //  4 byte
	double d;   //  8 byte(最大)
}s2;            // 24 byte

int main() {
	printf("%d\n",sizeof(s1));  //输出结果:32
	printf("%d\n",sizeof(s2));  //输出结果:24
	return 0;
}
图解1-1
在这里插入图片描述
在这里插入图片描述

如果结构体内部含有数组:(见图解1-2)

代码语言:javascript
复制
#include

// 当结构体成员包含数组:
struct str3 {
	int a;       //  4 byte
	double b;    //  8 byte(最大)  
	char arr[9]; //  9 byte(char基本数据类型占 1byte)
}s3;             //  结果:32

struct str4 {
	double b;    //  8 byte(最大)
	int a;       //  4 byte
	char arr[9]; //  9 byte(char基本数据类型占 1byte)
}s4;             //  结果:24

int main() {
	//如果结构体成员含有数组:
	printf("%d\n", sizeof(s3));  //输出结果:32
	printf("%d\n", sizeof(s4));  //输出结果:24
	return 0;
}
图解1-2
在这里插入图片描述
在这里插入图片描述

如果结构体中包含结构体:

代码语言:javascript
复制
#include

struct str5 {
	char ch;
	short sh;
	int num;
}s5;

struct str6 {
	int n;
	struct str5 s5;
}s6;

struct str7 {
	int n;
	char ch;
	short sh;
	int num;
}s7;

int main() {
	//如果结构体成员包含结构体:
	printf("%d\n", sizeof(s5));  //输出结果:8
	printf("%d\n", sizeof(s6));  //输出结果:12 --> sizeof(int)+8
	printf("%d\n", sizeof(s7));  //输出结果:12
	return 0;
}

结论:结构体 str6 和 str7等价,当结构体中成员包含结构体时 等价于 把成员结构体内容展开

注意:结构体成员包含的结构体不能为本身!

[完整代码如下]
代码语言:javascript
复制
#include

struct str1 {   //  内部求和为 18byte
	char a;     //  1 byte
	int b;      //  4 byte
	float c;    //  4 byte
	double d;   //  8 byte(最大)
	char ch;    //  1 byte
}s1;            //  结果:32 byte

// 将结构体成员变量调换位置后结构体内存占用发生改变:
struct str2 {   //  内部求和为 18byte
	char a;     //  1 byte
	char ch;    //  1 byte
	int b;      //  4 byte
	float c;    //  4 byte
	double d;   //  8 byte(最大)
}s2;            //  结果:24 byte

// 当结构体成员包含数组:
struct str3 {
	int a;       //  4 byte
	double b;    //  8 byte(最大)  
	char arr[9]; //  9 byte(char基本数据类型占 1byte)
}s3;             //  结果:32

struct str4 {
	double b;    //  8 byte(最大)
	int a;       //  4 byte
	char arr[9]; //  9 byte(char基本数据类型占 1byte)
}s4;             //  结果:24

// 当结构体成员包含结构体:
struct str5 {
	char ch;
	short sh;
	int num;
}s5;

struct str6 {
	int n;
	struct str5 s5;
}s6;

struct str7 {
	int n;
	char ch;
	short sh;
	int num;
}s7;

int main() {

	printf("%d\n",sizeof(s1));  //输出结果:32
	printf("%d\n",sizeof(s2));  //输出结果:24
	printf("\n");
	//如果结构体成员含有数组:
	printf("%d\n", sizeof(s3));  //输出结果:32
	printf("%d\n", sizeof(s4));  //输出结果:24
	printf("\n");
	//如果结构体成员包含结构体:
	printf("%d\n", sizeof(s5));  //输出结果:8
	printf("%d\n", sizeof(s6));  //输出结果:12
	printf("%d\n", sizeof(s7));  //输出结果:12
	return 0;
}

二.联合体的内存

规则:

1.大小必须足够容纳最宽的成员 2.大小能够被它所包含的所有的基本数据类型的大小整除

代码语言:javascript
复制
#include

union MyUnion1{
	char s[9];     //  9 byte (char类型为 1 byte)
	int n;         //  4 byte
	double d;      //  8 byte
};                 // 16 byte

union MyUnion2 {
	char s[5];     //  5 byte
	int n;         //  4 byte
	double d;      //  8 byte
};                 //  8 byte
int main() {
	printf("%d\n", sizeof(MyUnion1));     // 结果:16
	printf("%d\n", sizeof(MyUnion2));     // 结果:8
}

三.枚举的内存

代码语言:javascript
复制
#include

enum Enum {
	Enum1,      // (int) 4 byte
	Enum2,      // (int) 4 byte
	Enum3       // (int) 4 byte
}MyEnum;

int main() {
	printf("%d\n", sizeof(MyEnum));  // 结果:4
	printf("%d\n", sizeof(Enum1));   // 结果:4
	printf("%d\n", sizeof(Enum2));   // 结果:4
	printf("%d\n", sizeof(Enum3));   // 结果:4
	return 0;
}

关于枚举的解释大多数为:枚举皆为4字节;(例:如上情况)

——关于枚举内存的问题不必太深究,但是想探一探。

标准C语言描述没有明确规定枚举类型占用空间的大小,表示:“枚举类型的尺寸是以能够容纳最大枚举子值的整数的尺寸”,同时标准中也说明了: “枚举类型中的枚举子的值必须 能够 用一个int类型表述.”

代码语言:javascript
复制
#include

enum Enum {
	Enum1 = 0x7f7f7f7f7f,    // (int类型最大值) (int) 4 byte
	Enum2,                   //               (int) 4 byte
	Enum3,                   //               (int) 4 byte
	Enum4 = 5,
	Enum5,
    Enum6 = 0x7f7f7f7f7f,    //(int类型最大值)
	Enum7
}MyEnum;

int main() {
	printf("%d\n", sizeof(MyEnum));  // 结果:8
	printf("%d\n", sizeof(Enum1));   // 结果:8
	printf("%d\n", sizeof(Enum2));   // 结果:8
	printf("%d\n", sizeof(Enum4));   // 结果:4
    printf("%d\n", sizeof(Enum5));   // 结果:4
    printf("%d\n", sizeof(Enum6));   // 结果:8
    printf("%d\n", sizeof(Enum7));   // 结果:8
	return 0;
}

当枚举子值超过 int 范围时 得到枚举字节占用为 8 byte

本以为是枚举定义为 long 类型尺寸,但是发现子值的输出并非正确数值输出,依旧溢出;

此处可能与 int 类型的大小有关:

(关于 int 类型)其大小为计算机的字长,与cpu寄存器位数相关

一般情况:32位计算机为4字节 64位计算机为8字节

但在 x64 计算机环境调试结果多数仍然为4字节可能和编译器等多方面条件有关。

搜索资料中发现这样一篇文章:https://blog.csdn.net/HES_C/article/details/88668276

按照c语言描述可以实现,但本人未能实现。查询整理得到另一些合理解释:

具体内容如下:

1.转载:https://embedded.fm/blog/2016/6/28/how-big-is-an-enum

2.来自知乎留言:

在这里插入图片描述
在这里插入图片描述

enum本身并不以变量的方式存储到内存当中,但是将enum本身作为变量(包括指定具体是哪个枚举值),因为这个变量包含了枚举类型中的一部分值,所以会分配空间,这个具体值的大小,应该和机器、枚举值指定值有关系。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-01-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 数据结构类型(内存篇)超全结构体,联合,枚举内存解释(适用c语言入门)
    • 一.结构体的内存
      • 规则:
    • 二.联合体的内存
      • 规则:
    • 三.枚举的内存
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档