关于C/C++中结构体(Struct)类型的sizeof结果的探讨
2012-05-25 20:18
399 查看
关于C/C++中结构体(Struct)类型的sizeof结果的探讨
看了很多关于sizeof()的使用解释和说明,对于内置类型来说,基本没有什么问题,但是一旦将sizeof()用于结构体类型或其变量,就有点犯晕。很多地方没有给出一个可以套用的模式来说明其所得的结果是什么,有的说到了字节对其问题,例如,CPU的优化规则:对于n个字节的元素,它的首地址能被n整除,才能过的最好的性能。但是仅仅利用这一规则来推算sizeof的结果有时是不正确的。这也说明编译器并不是简单的按照这一规则进行地址分配。有的地方说了什么按字节对齐,大部分说的是按4字节对齐的方式进行推算,按字节对齐的目的很清楚,就是为了避免去一个数访问两次地址,例如,机器字为四个字节,系统为了提高速度,总是按四的倍数的方式存取内存,如果一个变量分配的地址是5(0为首地址)那么,需要首先取出地址编号为4-7的字节的内容,而后将第四个字节的内容舍弃,只保留第五到第七字节的,而后再去取8-11位置的字节,将编号8的字节拼接到上次取出的后三个字节后面,9-11舍弃不用,很明显,这样会严重的降低系统的性能。因此,编译器总是按字节对齐的方式分配地址,对于struct类型的分配,不能简单的按上面说的两种情况去推算,因为编译器并不是简单的那样做。下面探讨一下struct型的地址分配规律。
struct A
{
char a1;
char a2;
char a3;
};
结果为3;按一个字节对齐
struct A1
{
char a1;
char a2;
short a3;
};
结果为 4;按两个字节对齐
struct B
{
short a1;
short a2;
short a3;
};
结果为 6 。按两个字节对齐
struct B1
{
short a1;
short a2;
short a3
int a4;
};
结果为 12;按四个字节对齐
struct C
{
int a1;
int a2;
int a3;
};
结果为12; 按四个字节对齐
struct C1
{
int a1;
double d;
float f;
short s;
char c;
};
结果为 24 。按八个字节对齐
通过上面的测试我们可以看到,编译器在处理struct型的地址分配是有规律可循的,但并不是简答的按照上面的两种情况去做。而是更加的复杂一下:
1.首先确定本sizeof()中struct按几个字节对齐。很明显,是按结构体中的成员中的最大的那个类型字节数对齐。
2. 其次,保证分配是按1中确定的字节数对齐。也即是说,一是保证相对地址能够被其自身大小n整除 ,二是不能够取一个数访问两次地址。
下面在看一种情况
struct C2
{
int a1;
double d;
float f;
short s;
char c;
};
struct A2
{
char a1;
C2 c;
};
结果为 32;
其实对于成员是结构体类型的情况,只要将其展开即可。将其成员按顺序放入父结构体中即可。
看了很多关于sizeof()的使用解释和说明,对于内置类型来说,基本没有什么问题,但是一旦将sizeof()用于结构体类型或其变量,就有点犯晕。很多地方没有给出一个可以套用的模式来说明其所得的结果是什么,有的说到了字节对其问题,例如,CPU的优化规则:对于n个字节的元素,它的首地址能被n整除,才能过的最好的性能。但是仅仅利用这一规则来推算sizeof的结果有时是不正确的。这也说明编译器并不是简单的按照这一规则进行地址分配。有的地方说了什么按字节对齐,大部分说的是按4字节对齐的方式进行推算,按字节对齐的目的很清楚,就是为了避免去一个数访问两次地址,例如,机器字为四个字节,系统为了提高速度,总是按四的倍数的方式存取内存,如果一个变量分配的地址是5(0为首地址)那么,需要首先取出地址编号为4-7的字节的内容,而后将第四个字节的内容舍弃,只保留第五到第七字节的,而后再去取8-11位置的字节,将编号8的字节拼接到上次取出的后三个字节后面,9-11舍弃不用,很明显,这样会严重的降低系统的性能。因此,编译器总是按字节对齐的方式分配地址,对于struct类型的分配,不能简单的按上面说的两种情况去推算,因为编译器并不是简单的那样做。下面探讨一下struct型的地址分配规律。
struct A
{
char a1;
char a2;
char a3;
};
结果为3;按一个字节对齐
struct A1
{
char a1;
char a2;
short a3;
};
结果为 4;按两个字节对齐
struct B
{
short a1;
short a2;
short a3;
};
结果为 6 。按两个字节对齐
struct B1
{
short a1;
short a2;
short a3
int a4;
};
结果为 12;按四个字节对齐
struct C
{
int a1;
int a2;
int a3;
};
结果为12; 按四个字节对齐
struct C1
{
int a1;
double d;
float f;
short s;
char c;
};
结果为 24 。按八个字节对齐
通过上面的测试我们可以看到,编译器在处理struct型的地址分配是有规律可循的,但并不是简答的按照上面的两种情况去做。而是更加的复杂一下:
1.首先确定本sizeof()中struct按几个字节对齐。很明显,是按结构体中的成员中的最大的那个类型字节数对齐。
2. 其次,保证分配是按1中确定的字节数对齐。也即是说,一是保证相对地址能够被其自身大小n整除 ,二是不能够取一个数访问两次地址。
下面在看一种情况
struct C2
{
int a1;
double d;
float f;
short s;
char c;
};
struct A2
{
char a1;
C2 c;
};
结果为 32;
其实对于成员是结构体类型的情况,只要将其展开即可。将其成员按顺序放入父结构体中即可。
相关文章推荐
- 关于结构体struct的sizeof计算问题
- C++中 关于结构体中有char *类型的指针 赋值问题
- 关于结构体中的内存空洞、sizeof(struct)以及编译器优化的见解
- c++中关于类(class)和结构体(struct)的区别个人总结
- 关于struct类型的sizeof探究
- Struct结构体是C/C++语言中用来自定义数据类型的
- 关于c和c++中的struct类型
- C++中常见数据类型的sizeof值,以及计算struct和union的详细方法
- 关于结构体的内存分配问题--sizeof(/*struct*/A)
- c/c++中使用sizeof计算结构体struct和类class的长度(字节)
- 对c++类型做sizeof操作结果及分析
- C/C++ struct 结构体定义 用法详解
- 战30天C++入门极限-C/C++中结构体(struct)知识点强化(6)
- struct使用继承c++代码实例及运行结果
- 对结构体进行sizeof计算要点!!!不同编译器结果不一样,gcc宇VC就不一样
- 定义一个空类型,里面没有任何成员变量和成员函数。对该类型求sizeof 结果?
- 关于C和C++中的基本数据类型int、long、long long、float、double、char、string的大小及表示范围
- 【MVC】关于Action返回结果类型的事儿(上)
- C++中关于string类型究竟能不能用cout输出的问题