2010-05-30 73 views
5

好吧,我有我的C一个struct ++程序是这样的:含无符号的字符和INT的bug C++结构

struct thestruct 
{ 
unsigned char var1; 
unsigned char var2; 
unsigned char var3[2]; 
unsigned char var4; 
unsigned char var5[8]; 
int var6; 
unsigned char var7[4]; 
}; 

当我使用这个结构,3个随机字节获得“var6”前添加,如果我删除“var5”它仍然在“var6”之前,所以我知道它总是在“var6”之前。

但是,如果我删除了“var6”,那么3个额外的字节消失了。

如果我只使用一个带int的结构体,那么没有额外的字节。

所以在unsigned char和int之间似乎有冲突,我该如何解决这个问题?

回答

6

编译器可能使用其默认对齐选项,其中大小的成员X的存储器边界由整除对齐x

取决于你的编译器,你可以使用一个#pragma directive影响这种行为,例如:

#pragma pack(1) 

将关闭默认的对齐方式在Visual C++:

指定的值,以字节为单位,用于包装。为Ñ的缺省值是8。有效值是1,2,4,8和16。一个部件的对准将是一个边界要么是一个的Ñ倍数或的大小的倍数上该成员,以较小者为准。

注意,对于低级别的CPU性能方面的原因,它通常是最好的尝试,以您的数据成员对齐,使他们落入对齐边界上。某些CPU架构需要对齐,而另一些CPU架构(如Intel x86)容忍未对齐,性能下降(有时非常显着)。

+0

谢谢你的工作 – powerfear 2010-05-30 04:33:10

4

你说的是填充字节吗?这不是一个错误。正如C++标准所允许的,编译器正在添加填充以保持成员aligned。这对于某些体系结构是必需的,并且会大大提高其他体系的性能。

5

你的数据结构是aligned让你的INT落在单词boundries,这对于你的目标可能是32或64位。
您可以重新组织你的结构像这样,使这不会发生:

struct thestruct 
{ 
int var6; 
unsigned char var1; 
unsigned char var2; 
unsigned char var3[2]; 
unsigned char var4; 
unsigned char var5[8]; 
unsigned char var7[4]; 
}; 
+0

好的调用重组结构,比使用编译器相关的打包编译指示/属性要好得多。 – 2010-05-30 11:49:35

+0

虽然它仍然是实现定义的。 – 2010-12-11 21:05:48

0

你有一个字节对齐问题。编译器正在添加填充以对齐字节。请参阅this维基百科文章。

0

阅读上data structure alignment。实质上,根据编译器和编译选项,您将得到不同的2的权力。

为了避免它,单字节(符号或无符号字符)项目前移到多字节项目(INT或指针) - 尽管它仍然可能是后您的最后一个项目有

0

虽然重新安排你声明的数据成员的顺序您struct里面是好的,但应该强调的是,通过使用#pragma小号覆盖默认对齐和这样一个坏主意,除非你知道自己在做什么。根据您的编译器和体系结构,尝试访问未对齐的数据(尤其是通过将地址存储在指针中并稍后尝试对其进行解引用)可能会轻松导致可怕的总线错误或其他未定义的行为。