漫谈c语言结构体
再看看char_long_short这个结构体,char_long_short的地址分布情况如下表:
成员变量 |
成员变量十六进制地址 |
成员变量十进制地址 |
char_long_short.c |
0x0012FF2C |
1244972 |
char_long_short.l |
0x0012FF30 |
1244976 |
char_long_short.s |
0x0012FF34 |
1244980 |
可见,其内存分布图如下,共12bytes:
地址 |
1244972 |
1244973 |
1244974 |
1244975 |
1244976 |
1244977 |
1244978 |
1244979 |
1244980 |
1244981 |
1244982 |
1244983 |
成员 |
.c |
.l |
.s |
首先,1244972能被1整除,所以char_long_short.c放在1244972处没有问题(其实,就char型成员变量自身来说,其放在任何地址单元处都没有问题),根据原则1,在之后的1244973~1244975中都没有能被4(因为sizeof(long)=4bytes)整除的,1244976能被4整除,所以char_long_short.l应该放在1244976处,那么同理,最后一个.s(sizeof(short)=2bytes)是应该放在1244980处。
是不是这样就结束了?不是,还有原则2。根据原则2的要求,char_long_short这个结构体所占的空间大小应该是其占内存空间最大的成员变量的大小的整数倍。如果我们到此就结束了,那么char_long_short所占的内存空间是1244972~1244981共计10bytes,不符合原则2,所以,必须在最后补齐2个bytes(1244982~1244983)。
至此,一个结构体的内存布局完成了。
下面我们按照上述原则,来验证这样的分析是不是正确。按上面的分析,地址单元1244973、1244974、1244975以及1244982、1244983都是空的(至少char_long_short未用到,只是“占位”了)。如果我们的分析是正确的,那么,定义这样一个结构体,其所占内存也应该是12bytes:
struct//声明结构体char_long_short_new
{
charc;
charadd1;//补齐空间
charadd2;//补齐空间
charadd3;//补齐空间
longl;
shorts;
charadd4;//补齐空间
charadd5;//补齐空间
}char_long_short_new;
运行结果如下:
可见,我们的分析是正确的。至于原则3,大家可以自己编程验证,这里就不再讨论了。
所以,无论你是在VC6.0还是KeilC51,还是KeilMDK中,当你需要定义一个结构体时,只要你稍微留心结构体成员变量内存对齐这一现象,就可以在很大程度上节约MCU的RAM。这一点不仅仅应用于实际编程,在很多大型公司,比如IBM、微软、百度、华为的笔试和面试中,也是常见的。
本例完整的程序代码下载:http://www.51hei.com/f/cjgt.rar
评论