探究struct中每个类型内存容量的大小及总内存大小的关系

2022.1.27实验

实验目的:探究struct中每个类型内存容量的大小及总内存大小的关系

总实验如下:

#include<stdio.h>
//对结构的研究
struct structure0 {
	double a;	
	char b;
};
struct structure1 {
	char a;	
	double b;
	char c;
};
struct structure2 {
	int a;
	int b;
	double c;
	int d;
	int e;
};
struct structure3 {
	int a;
	int b;
	char c;
};
int main() {
	struct structure1 a;
	struct structure2 b;
	struct structure3 c;
	struct structure0 d; 
	printf("%u=%u+%u+%u?\n",sizeof(a),sizeof(a.a),sizeof(a.b),sizeof(a.c));//多了3 
	printf("a:%p a.a:%p a.b:%p a.c:%p\n",&a,&a.a,&a.b,&a.c);
	printf("%u=%u+%u+%u+%u+%u?\n",sizeof(b),sizeof(b.a),sizeof(b.b),sizeof(b.c),sizeof(b.d),sizeof(b.e));//多了4 
	printf("b:%p b.a:%p b.b:%p b.c:%p b.d:%p b.e:%p\n",&b,&b.a,&b.b,&b.c,&b.d,&b.e);
	printf("%u=%u+%u+%u?\n",sizeof(c),sizeof(c.a),sizeof(c.b),sizeof(c.c));//多了3 
	printf("c:%p c.a:%p c.b:%p c.c:%p\n",&c,&c.a,&c.b,&c.c);//指针地址为元素首地址,连续排列 
	printf("%u=%u+%u?\n",sizeof(d),sizeof(d.a),sizeof(d.b));
	printf("d:%p d.a:%p d.b:%p\n",&d,&d.a,&d.b);
	/*
	猜测1:结构的sizeof与结构中的变量类型有关; 
	猜测2:若结构类型全部一致,则sizeof即为所有类型之和,比如所有四个元素都是int,则是16字节;
	若结构类型中有一个与其它不一样,则sizeof为所有类型之和加上元素个数;经验证猜想2不正确 
	猜测3:当结构中有连续不满4个char类型时,分配给它的都是4个字节地址;
	猜测4:当结构中只有一个char时,和最临近的前面那个类型的大小一样;
	猜测5:当结构中优先级高的在前面则后面默认使用优先级高的地址的大小,比如double在int前则是16;
	若int在double前也是12; 
	*/ 
}

🍎初步实验A:两个元素的结构

1.int&double

struct structure0 {
	int a;	
	double b;
};
struct structure0 d; 
printf("%u=%u+%u?\n",sizeof(d),sizeof(d.a),sizeof(d.b));
printf("d:%p d.a:%p d.b:%p\n",&d,&d.a,&d.b);

结果为:

16=4+8?
d:0061fe98 d.a:0061fe98 d.b:0061fea0

分析:由于后面的double需要连续8个字节,所以导致默认前面也是8个字节这样过来的;

换一下顺序,

struct structure0 {
	double a;
    int b;	
};

同样也是16;

2.int&char

struct structure0 {
	int a;	
	char b;
};
struct structure0 d; 
printf("%u=%u+%u?\n",sizeof(d),sizeof(d.a),sizeof(d.b));
printf("d:%p d.a:%p d.b:%p\n",&d,&d.a,&d.b);

结果

8=4+1?
d:0061fea0 d.a:0061fea0 d.b:0061fea4

分析:正确,char也分配了优先级较高的地址

struct structure0 {
	char a;	
	int b;
};

所分配地址同样也是8;

3.char&double

都是16;

符合上面实验猜想:由优先级高的类型决定每个内存空间大小;

🍰进一步实验B:三个元素的结构

1.int&char

struct structure1 {
	int a;	
	int b;
	char c;
};

如图定义了一个struct,下面测量其大小,

struct structure1 a;
printf("%u=%u+%u+%u?\n",sizeof(a),sizeof(a.a),sizeof(a.b),sizeof(a.c));
printf("a:%p a.a:%p a.b:%p a.c:%p\n",&a,&a.a,&a.b,&a.c);
12=4+4+1?
a:0061fec4 a.a:0061fec4 a.b:0061fec8 a.c:0061fecc

经验证,即使交换char的位置,也符合地址大小是12个字节;

但是,这种

struct structure1 {
	int a;	
	char b;
	char c;
};

和这种

struct structure1 {
	char a;	
	char b;
	int c;
};

都是8个字节,

显然与之前预测到的结果有点不一样,(但是我们节约了空间),相比于下面这种

struct structure1 {
	char a;	
	int b;
	char c;
};

这是12个字节;

我们开始发现了不同之处,好像C语言内部挺智能的:当它检测到又两个较小的类型连续排列时就干脆把它们一同塞进同一个较大字节空间里;

2.int&double

我们试着模仿上面的过程,将上面(int&char)程序中的所有char换成较小类型的int,把所有int换成了较大类型的double;发现事情正好如我们所料,当较小类型连续排列时,两个int干好被塞到一个double一样大的空间去了(16个字节),而如果double被夹在中间时则显得相当浪费空间(24个字节),

struct structure1 {
	int a;	
	double b;
	int c;
};

我们于是发现了不一样并不是真正的不一样,只能说这个叫做"有机统一",及并不是所有的小类型都必须获得一个大类型的空间,当他们在一起时,他们完全可以共享,所以还要给初步实验的结论加一个限制条件:

由优先级高的类型决定每个内存空间大小,当优先级低的类型连续排列时,他们可以在同一个内存空间中

所以同样的内存空间(24个字节),我们完全可以这样写(多两个int):

struct structure2 {
	int a;
	int b;
	int c;
	int d;
	double e;
};
printf("%u=%u+%u+%u?\n",sizeof(a),sizeof(a.a),sizeof(a.b),sizeof(a.c));
printf("a:%p a.a:%p a.b:%p a.c:%p\n",&a,&a.a,&a.b,&a.c);
printf("%u=%u+%u+%u+%u+%u?\n",sizeof(b),sizeof(b.a),sizeof(b.b),sizeof(b.c),sizeof(b.d),sizeof(b.e)); 
printf("b:%p b.a:%p b.b:%p b.c:%p b.d:%p b.e:%p\n",&b,&b.a,&b.b,&b.c,&b.d,&b.e);
24=4+8+4?
a:0061feb8 a.a:0061feb8 a.b:0061fec0 a.c:0061fec8
24=4+4+4+4+8?
b:0061fea0 b.a:0061fea0 b.b:0061fea4 b.c:0061fea8 b.d:0061feac b.e:0061feb0

3.char&double

或者说夸张一点,

struct structure1 {
	char a;	
	double b;
	char c;
};

这是24个字节的空间,我们可以写七个字符其实

#include<stdio.h>
//对结构的研究下
struct structure4{
	char* a;
	char* b;
	double c;
}; 
 
int main(){
	struct structure4 k;
	k=(struct structure4){"Ohhhhhh","<@^_^@>",2.0};
	printf("%u=%u+%u+%u?\n",sizeof(k),sizeof(k.a),sizeof(k.b),sizeof(k.c));
	printf("k:%p k.a:%p k.b:%p k.c:%p\n",&k,&k.a,&k.b,&k.c);
	printf("%s %s %lf",k.a,k.b,k.c );
	
}
16=4+4+8?
k:0061fec0 k.a:0061fec0 k.b:0061fec4 k.c:0061fec8
Ohhhhhh <@^_^@> 2.000000

这也只有16字节而已;

由此我们总结四条原则,(之所以不在最后结尾处才总结完全是因为我喜欢😄):

🍌定义你的结构时最好把相同类型的放在一起,这样节省空间;

🍊对于结构或字符串这些比较大的东西,我们可以向数组学习,传一个只有4字节的指针就好了;

🍍可能在内存越来越大的未来(可能明天又发布新显卡),几个字节算不了,但是节省空间,学会控制一点总是好的;

🐑做实验或者验证你的想法都应该从少到多,从简单到复杂,我们只有从简单的,从单一变量出发,才能总结出最纯朴的道理,如果同时改变几个变量而加以观测,我们很容易将两个道理糅合起来说出其它奇怪的想法,(偏见),因为那时我们对每个变量的观察并不是平均的;

4.char&double&int

struct structure1 {
	char a;	
	double b;
	int c;
};

24个字节;

struct structure4{
	char a;
	int b;
	double c;
}; 

16个字节;

这些都验证了我们的猜想,所以我们以后也建议写结构时先把简单的放在前面,到后面时就不会把简单的也分配较大的空间,(发现这与考试是及其相似的,先易后难,不要让过于难的东西搅浑了我们的心态)

玩的,还挺好玩的😂🍑⛽💁‍♂️

posted @ 2022-01-27 18:24  Link_kingdom  阅读(96)  评论(0编辑  收藏  举报