内存对齐问题--vs2010下位域结构体对齐规则

请写出一下代码的输出结果:

// interface.cpp : 定义控制台应用程序的入口点。
//内存对齐
#include "stdafx.h"
#include 
#include 
struct s1
{
	int i:8;
	char j:4;
	int a:4;
	double b;
};

struct s2
{
	int i:8;
	int j:4;
	double b;
	int a:4;
};
struct s3
{
	int i;
	char j;
	double b;
	int a;
};
struct s4
{
	int i:8;
	int j:4;
	int a:3;
	double b;
};
struct s5
{
	int i:8;
	int j:4;
	double b;
	int a:3;
};

struct name1
{
	char str;
	short x;
	int num;
};
struct name2
{
	char str;
	int num;
	short x;
};

int _tmain(int argc, _TCHAR* argv[])
{
	memset((struct s1 *)(0x0012FF48),0,sizeof(struct s1));
     struct	s1 s;
	s.i=1;
	s.j=2;
	s.a=3;
	s.b=3;
	printf("%d\t",sizeof(s1));
	printf("%d\t",sizeof(s2));
	printf("%d\t",sizeof(s3));
	printf("%d\t",sizeof(s4));
	printf("%d\t",sizeof(s5));
	printf("%d\t",sizeof(name1));
	printf("%d\t",sizeof(name2));
	return 0;
}

按照位域内存对齐规则并参考http://www.cppblog.com/snailcong/archive/2009/03/16/76705.html,分析得知sizeof(s1)=16,而vs2010给出的答案是24,纠结了一下午也没给出一个明确的答案,先把疑问写出来,慢慢来求解。
对于比较难解决的问题,最好不要依赖printf,直接按F10,在监视1看了下变量s的地址是0x0012FF48,所以在memset里会出现0x0012FF48这个地址,为了把变量s在内存中所占区域清零,然后在内存1中查看0x0012FF48起始的内存块,如下图所示:

从图中可以看出vs内存对齐规则是4(int)+1(char)+3(扩展)+4(int)+4(扩展)+8(double),很明显就没按位域对齐规则来存储,而是按照普通的一个结构体来进行内存对齐,难道这是vs2010的一个小bug?待求解!
在网上搜索了一番,终于解开了谜题,http://www.diybl.com/course/3_program/c++/cppsl/20090311/160450.html# 这篇文章写得很好,解释的很清楚,对于位域存储规则的处理不同编译器处理规则不一样。(以下文字来自于http://www.diybl.com/course/3_program/c++/cppsl/20090311/160450.html#)
如果结构体中含有位域(bit-field),那么VC中准则又要有所更改:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式(不同位域字段存放在不同的位域类型字节中),Dev-C++和GCC都采取压缩方式;

你可能感兴趣的:(c面试题)