数据结构类型(内存篇)
一.结构体的内存
内存对齐
规则:
1.结构体的第一个数据成员存放的地址为结构体变量偏移量为 0 的地址处.
2.其他起始地址为该类型变量所占内存的整数倍,如果不足部分用数据填充到所占内存的整数倍
3.结构体所占总内存为该结构体的成员中基本数据类型占字节数最大的整数倍
(见图解1-1)
#include<stdio.h>
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)
#include<stdio.h>
// 当结构体成员包含数组:
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
如果结构体中包含结构体:
#include<stdio.h>
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等价,当结构体中成员包含结构体时 等价于 把成员结构体内容展开
注意:结构体成员包含的结构体不能为本身!
[完整代码如下]
#include<stdio.h>
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.大小能够被它所包含的所有的基本数据类型的大小整除
#include<stdio.h>
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
}
三.枚举的内存
#include<stdio.h>
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类型表述.”
#include<stdio.h>
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.来自知乎留言:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1D43Ryqp-1644332606219)(3-1.png)]
计算机为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本身作为变量(包括指定具体是哪个枚举值),因为这个变量包含了枚举类型中的一部分值,所以会分配空间,这个具体值的大小,应该和机器、枚举值指定值有关系。