C++类和结构体,通过new/malloc的,一般都在堆上存储。
他们和基本数据类型int,char等一样,具体在内存哪个区域看声明的区域:
在函数内的局部变量,则在栈上;静态变量或全局变量则在静态存储区。
结构体大小的计算:
一般来说,结构体大小,不等于内部成员的大小之和。
原则一:结构体中元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排列的。从结构体存储的首地址开始,每一个元素放置到内存中时,它都会认为内存是以它自己的大小来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始(以结构体变量首地址为0计算)。
#include<stdio.h>
struct A{
char a;//1
int b;//4
char c;//1
int* d;//8
};
int main(){
printf("%dn", sizeof(struct A));//24
return 0;
}
环境:win 64位,即机器读取内存,一次读取64位-8字节。
首先,按照定义顺序,先放char a在地址0,char占一个字节;
其次,存储int b,放在模4为空的第一个位置,即地址4,int占4个字节,地址编号4 5 6 7的内存空间都是Int b 的空间,变量a和b中间的地址为1 2 3的空间为填充占位;
然后,存放char c,放在地址8,char占一个字节;
最后,指针变量d,指针8个字节,找模8为空的第一个位置,地址0不行,地址8不行,地址16可以,因此地址16到23存放指针d,其中c和d之间的地址编号为9-15的为占位空间。
sizeof(A)=24
#include<stdio.h>
struct A{
char c;//1
char b;//1
int* d;//8
int a;//4
};
int main(){
printf("%dn", sizeof(struct A));//24
return 0;
}
按照上述计算,得到20,而程序输出24,由此引出原则2:
原则二:在经过第一原则分析后,检查计算出的存储单元是否为所有元素中最宽的元素的长度的整数倍,是,则结束;若不是,则补齐为它的整数倍。
最后放int a,需要补齐8个字节来对齐。
总结:
结构体大小未必等于成员大小的和;
按照内存对齐,成员位置在模自己长度为0的第一个空位;
最后,需要按照最宽成员进行内存补齐。
因此,为了节省结构体所占内存空间:
可以按照元素需要内存的大小排序,降序排序,
并且同类型的尽量临近声明。
#include<stdio.h>
struct A{
int* d;//8
int a;//4
char c;//1
char b;//1
};
int main(){
printf("%dn", sizeof(struct A));//16
return 0;
}