union{
BYTE a[7];
struct{
BYTE b;
WORD c;
DWORD e;
}t1;
}t;
先往数组a中赋值,然后从结构体中取变量b c e ,为什么结果总是不对呢b应该是a[0];c应该是a[1]a[2]的组合啊;e应该是a[3]a[4]a[5]a[6]的组合啊!试了很多遍总也不对,高手给指点一下拉!小弟万分感谢!
5 个解决方案
#1
你cout<<sizeof(t)<<endl;看看;这涉及到内存对齐
#2
是数据对齐的问题,sizeof(t.t1) = 8,c从结构的第三个字节分配,e从第五个字节,b占一个字节,b后面一个字节为空,总共占用8个字节,而a数组为7个字节,所以你得到的结果不正确。
#3
对齐规则由编译选项决定的,一般编译器采用缺省的编译选项。一般存储单元按照CPU的字长对齐,对于目前32位主流系统,基本的数据类型char、short、int、float,对齐在整字的开始。
如struct
{
char c;
int i;
float f;
};
c占用第一个字长的第一个字节,而后面的3个字节变长存储空洞;i和f各占1个字长。
struct
{
char c;
char c1;
int i;
float f;
};
这种情况下,c1将分配在c之后,占一个字节,而c1后面就留出来2各空洞(专业术语padding填充)。
所以在组织struct或者class时,注意一下成员分布的合理,综合一下存储分配情况。但是从CPU的指令操作上看,CPU一般按照一个字长来执行,操作一个int数要比一个char效率高。也就说说,当CPU读取一个char数时,CPU先从内存中读取一整个字长值到寄存器中,然后将相应char所在的那个字节提取出来,从而完成一个char的取值。
如果编译选项采用1字节、2字节、4字节、8字节对齐,那么同样的道理,可以自己分析一下吧。
另外:编程时千万注意float *pFVal;指针的使用,浮点数指针一定要指向一个整字起始的内存位置,如上面的&c1地址,否则在一些特定的CPU或单片机中,对非对齐的浮点指针操作,会发生崩溃问题,这个和浮点指令的兼容性问题。典型的是在sun的sparc、POWERPC的一些cpu上就会发生崩溃问题。
如struct
{
char c;
int i;
float f;
};
c占用第一个字长的第一个字节,而后面的3个字节变长存储空洞;i和f各占1个字长。
struct
{
char c;
char c1;
int i;
float f;
};
这种情况下,c1将分配在c之后,占一个字节,而c1后面就留出来2各空洞(专业术语padding填充)。
所以在组织struct或者class时,注意一下成员分布的合理,综合一下存储分配情况。但是从CPU的指令操作上看,CPU一般按照一个字长来执行,操作一个int数要比一个char效率高。也就说说,当CPU读取一个char数时,CPU先从内存中读取一整个字长值到寄存器中,然后将相应char所在的那个字节提取出来,从而完成一个char的取值。
如果编译选项采用1字节、2字节、4字节、8字节对齐,那么同样的道理,可以自己分析一下吧。
另外:编程时千万注意float *pFVal;指针的使用,浮点数指针一定要指向一个整字起始的内存位置,如上面的&c1地址,否则在一些特定的CPU或单片机中,对非对齐的浮点指针操作,会发生崩溃问题,这个和浮点指令的兼容性问题。典型的是在sun的sparc、POWERPC的一些cpu上就会发生崩溃问题。
#4
#pragma pack(push, 1)
union{
BYTE a[7];
struct{
BYTE b;
WORD c;
DWORD e;
}t1;
}t;
#pragma pack(pop)
union{
BYTE a[7];
struct{
BYTE b;
WORD c;
DWORD e;
}t1;
}t;
#pragma pack(pop)
#5
多些各位啊!小弟明白啦!
#1
你cout<<sizeof(t)<<endl;看看;这涉及到内存对齐
#2
是数据对齐的问题,sizeof(t.t1) = 8,c从结构的第三个字节分配,e从第五个字节,b占一个字节,b后面一个字节为空,总共占用8个字节,而a数组为7个字节,所以你得到的结果不正确。
#3
对齐规则由编译选项决定的,一般编译器采用缺省的编译选项。一般存储单元按照CPU的字长对齐,对于目前32位主流系统,基本的数据类型char、short、int、float,对齐在整字的开始。
如struct
{
char c;
int i;
float f;
};
c占用第一个字长的第一个字节,而后面的3个字节变长存储空洞;i和f各占1个字长。
struct
{
char c;
char c1;
int i;
float f;
};
这种情况下,c1将分配在c之后,占一个字节,而c1后面就留出来2各空洞(专业术语padding填充)。
所以在组织struct或者class时,注意一下成员分布的合理,综合一下存储分配情况。但是从CPU的指令操作上看,CPU一般按照一个字长来执行,操作一个int数要比一个char效率高。也就说说,当CPU读取一个char数时,CPU先从内存中读取一整个字长值到寄存器中,然后将相应char所在的那个字节提取出来,从而完成一个char的取值。
如果编译选项采用1字节、2字节、4字节、8字节对齐,那么同样的道理,可以自己分析一下吧。
另外:编程时千万注意float *pFVal;指针的使用,浮点数指针一定要指向一个整字起始的内存位置,如上面的&c1地址,否则在一些特定的CPU或单片机中,对非对齐的浮点指针操作,会发生崩溃问题,这个和浮点指令的兼容性问题。典型的是在sun的sparc、POWERPC的一些cpu上就会发生崩溃问题。
如struct
{
char c;
int i;
float f;
};
c占用第一个字长的第一个字节,而后面的3个字节变长存储空洞;i和f各占1个字长。
struct
{
char c;
char c1;
int i;
float f;
};
这种情况下,c1将分配在c之后,占一个字节,而c1后面就留出来2各空洞(专业术语padding填充)。
所以在组织struct或者class时,注意一下成员分布的合理,综合一下存储分配情况。但是从CPU的指令操作上看,CPU一般按照一个字长来执行,操作一个int数要比一个char效率高。也就说说,当CPU读取一个char数时,CPU先从内存中读取一整个字长值到寄存器中,然后将相应char所在的那个字节提取出来,从而完成一个char的取值。
如果编译选项采用1字节、2字节、4字节、8字节对齐,那么同样的道理,可以自己分析一下吧。
另外:编程时千万注意float *pFVal;指针的使用,浮点数指针一定要指向一个整字起始的内存位置,如上面的&c1地址,否则在一些特定的CPU或单片机中,对非对齐的浮点指针操作,会发生崩溃问题,这个和浮点指令的兼容性问题。典型的是在sun的sparc、POWERPC的一些cpu上就会发生崩溃问题。
#4
#pragma pack(push, 1)
union{
BYTE a[7];
struct{
BYTE b;
WORD c;
DWORD e;
}t1;
}t;
#pragma pack(pop)
union{
BYTE a[7];
struct{
BYTE b;
WORD c;
DWORD e;
}t1;
}t;
#pragma pack(pop)
#5
多些各位啊!小弟明白啦!