先分析一下下面这段代码
#include<stdio.h>
struct num{
char na;
int a;
int b;
double aa;
}num1;
int main(void){
printf("%d %d\n",sizeof(int),sizeof(double));
printf("%d",sizeof(num1));
return 0;
}
首先给出一段代码按照正常的思路char类型一个字节,int 占4个字节,一个double是8个字节那么这个结构体的大小按理应该分配在1+4+4+8=17个字节可是结果到底是什么呢?我们看一下运行的结果。
8
24
--------------------------------
Process exited after 10.83 seconds with return value 0
请按任意键继续. . .
what?怎么回事,多出来这么多的字节?不要着急。
下面先让我们进行一下假设和理论分析然后通过实验探究,最后得出一般结论。
首先我的系统是64位的,编程内存一般分配为16个字节为一段。也就是像这样理解内存在我的电脑里的分布。
地址: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
值: |
地址: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
值: |
我们先来往里面填变量遇到不够的就直接开始下一行,最后如下
地址: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
值: | char | int | int | int | int | int | int | int | int |
0地址是char na所占的长度 1~8地址分别是int a,int b所占长度;
可以看到当分配完int b后剩下的内存长度已经容不下一个double类型的变量了;
所以就跳到下一行内存带开始写变量;
地址: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
值: | dd | dd | dd | dd | dd | dd | dd | dd |
所以我们假设分配到的内存大小就是16+8=24看样子和实验结果符合,但还不确定一定就是正确的,我要再做实验来验证。
怎样来验证呢?我们只需要计算int b变量的首地址与double aa首地址的差是否为8就行了
修改代码如下
#include<stdio.h>
struct num{
char na;
int a;
int b;
double aa;
}num1;
int main(void){
printf("%d %d\n",sizeof(int),sizeof(double));
printf("%d\n",sizeof(num1));
// printf("%d",&num1.aa-&num1.b);
printf("struct %p char na %p int a %p int b %p double aa %p\n",&num1,&num1.na,&num1.a,&num1.b,&num1.aa);
return 0;
}
最后运行结果为
4 8
24
struct 0000000000408A70
char na 0000000000408A70
int a 0000000000408A74
int b 0000000000408A78
double aa 0000000000408A80
--------------------------------
Process exited after 10.46 seconds with return value 0
请按任意键继续. . .
这里我们可以看到结构体的地址就是其内第一个变量的地址,和估计的是分毫不差。
写到这里我相信对结构体的一个内存分布是有了一个比较清晰的认识。