C语言中位段内存的探讨研究
目录
由于位段的特殊性,本文用的是VS编译器,其他编译器的结果可能是不同的。以在同一个位段中分别定义int,char,long long为例,这是因为三者所占大小具有一定的代表性,是不同的。经过几次测试,我发现同一个类型如果相邻且有多个的话,会占据同一快新开辟的内存,所以这里只以一个char或者int或者long long类型为例。
所有的测试前一个是代码内容,后面的图片是内存测试结果以及结论。
1.char->int
struct S
{
char a : 2;
int b : 2;
};
int main()
{
struct S s= { 0 };
s.a = 2;
s.b = 2;
return 0;
}

当定义顺序为char->int时,先为char开辟四个字节的空间,然后再重新为下面的int开辟四个字节的空间。再强调一下,如果char类型前面还有char类型,或者int类型后面还有int类型,则为它们开辟的空间仍然在为char开辟,或者为int开辟的空间中。
2.char->long long
struct S
{
char a : 2;
long long b : 2;
};
int main()
{
struct S s= { 0 };
s.a = 2;
s.b = 2;
return 0;
}

当顺序为char->long long时,先为char开辟8个字节的空间,再为long long重新开辟8个字节的空间。
3.int->char
struct S
{
int a : 2;
char b : 2;
};
int main()
{
struct S s= { 0 };
s.a = 2;
s.b = 2;
return 0;
}
当定义顺序为int->char时,会先为int开辟四个字节的空间,然后再为char开辟四个字节的空间。
4.long long->char
struct S
{
long long a : 2;
char b : 2;
};
int main()
{
struct S s= { 0 };
s.a = 2;
s.b = 2;
return 0;
}
当顺序为long long->char时,会先为long long开辟8个字节的空间,然后为char 开辟8个字节的空间。
5.int->long long
#include<stdio.h>
struct S
{
int a : 2;
long long b : 2;
};
int main()
{
struct S s= { 0 };
s.a = 2;
s.b = 2;
return 0;
}

当顺序为int->long long时,会先为int开辟8个字节,然后再为long long开辟8个字节。
6.long long->int
#include<stdio.h>
struct S
{
long long a : 2;
int b : 2;
};
int main()
{
struct S s= { 0 };
s.a = 2;
s.b = 2;
return 0;
}

当定义顺序为long long->int 时,先为long long开辟8个字节,再为int 开辟8个字节。
7.char->int->long long
#include<stdio.h>
struct S
{
char a : 2;
int b : 2;
long long c : 2;
};
int main()
{
struct S s= { 0 };
s.a = 2;
s.b = 2;
s.c = 2;
return 0;
}

先为char分配4个字节,然后为int分配4个字节,最后为long long分配8个字节。
8.char->long long->int
#include<stdio.h>
struct S
{
char a : 2;
long long b : 2;
int c : 2;
};
int main()
{
struct S s= { 0 };
s.a = 2;
s.b = 2;
s.c = 2;
return 0;
}

当顺序为char->long long->int时,先为char分配8个字节,再为long long分配8个字节,最后为int分配8个字节。
9.int->char->long long
#include<stdio.h>
struct S
{
int a : 2;
char b : 2;
long long c : 2;
};
int main()
{
struct S s= { 0 };
s.a = 2;
s.b = 2;
s.c = 2;
return 0;
}

当顺序为int->char->long long时,先为int分配4个字节,再为char分配4个字节,最后为long long分配8个字节。
10.int->long long->char
#include<stdio.h>
struct S
{
int a : 2;
long long b : 2;
char c : 2;
};
int main()
{
struct S s= { 0 };
s.a = 2;
s.b = 2;
s.c = 2;
return 0;
}

当顺序为int->long long->char时,先为int分配8个字节,再为long long分配8个字节,最后为char分配8个字节。
11.long long->int->char
#include<stdio.h>
struct S
{
long long a : 2;
int b : 2;
char c : 2;
};
int main()
{
struct S s= { 0 };
s.a = 2;
s.b = 2;
s.c = 2;
return 0;
}

当顺序为long long->int->char,会先为long long分配8个字节的内存,然后为int分配4个字节,最后为char分配4个字节。
12.long long->char->int
#include<stdio.h>
struct S
{
long long a : 2;
char b : 2;
int c : 2;
};
int main()
{
struct S s= { 0 };
s.a = 2;
s.b = 2;
s.c = 2;
return 0;
}

当顺序为long long->char->int时,先为long long分配8个字节的内存,然后为char开辟4个字节的空间,最后为int开辟4个字节的空间。
13.结论罗列
char->int,先为char开辟四个字节的空间,然后再重新为下面的int开辟四个字节的空间。
char->long long,先为char开辟8个字节的空间,再为long long重新开辟8个字节的空间。
int->char,会先为int开辟四个字节的空间,然后再为char开辟四个字节的空间。
long long->char,会先为long long开辟8个字节的空间,然后为char 开辟8个字节的空间。
int->long long,会先为int开辟8个字节,然后再为long long开辟8个字节。
long long->int ,先为long long开辟8个字节,再为int 开辟8个字节
char->int->long long,先为char分配4个字节,然后为int分配4个字节,最后为long long分配8个字节。
char->long long->int,先为char分配8个字节,再为long long分配8个字节,最后为int分配8个字节。
int->char->long long,先为int分配4个字节,再为char分配4个字节,最后为long long分配8个字节。
int->long long->char,先为int分配8个字节,再为long long分配8个字节,最后为char分配8个字节。
long long->int->char,会先为long long分配8个字节的内存,然后为int分配4个字节,最后为char分配4个字节。
long long->char->int,先为long long分配8个字节的内存,然后为char开辟4个字节的空间,最后为int开辟4个字节的空间。
14.总结
我们把数据分为按类型顺序分为两组,得出结论:
结论一:
当一个位段中只有两种类型的时候,每次对类型变量进行空间分配时,分配空间大小为最大类型的大小,且每换一个类型就要重新分配一段空间。
结论二:
当一个位段中定义了三种类型的时候,每次对类型进行空间分配时,
当最大的类型定义在两种中间的时候,为三个类型分配的空间均为第三个类型所占空间。
其他情况中,最大的类型占其应占的最大空间,剩下两个类型占两者之间最大的类型所占的空间。
同时博主用char,short,int和short,int,long long均做了检验结论是相同的。
当位段中有四个类型时,我尝试过总结,情况更为复杂,但毕竟位段的性质和编译器是分不开的,这里只是在VS编译器发现的结果,所以没有再进行四个类型的研究。感兴趣的大佬们可以尝试总结一下呀,然后可以分享一下。



浙公网安备 33010602011771号