Posted on 2005-04-02 23:49 Panic 阅读(18705)
评论(43) 编辑 收藏
结构体对齐的具体含义(#pragma pack)
作者:panic 2005年4月2日
还是来自csdn的帖子:
主 题: 探讨:内存对齐
作 者: typedef_chen ((名未定)(我要骗人))
等 级:
信 誉 值: 100
所属论坛: C/C++ C++ 语言
问题点数: 50
回复次数: 1
发表时间: 2005-04-02 22:53:27
朋友帖了如下一段代码:
#pragma pack(4)
class TestB
{
public:
int aa;
char a;
short b;
char c;
};
int nSize = sizeof(TestB);
这里nSize结果为12,在预料之中。
现在去掉第一个成员变量为如下代码:
#pragma pack(4)
class TestC
{
public:
char a;
short b;
char c;
};
int nSize = sizeof(TestC);
按照正常的填充方式nSize的结果应该是8,为什么结果显示nSize为6呢?
事实上,很多人对#pragma pack的理解是错误的。
#pragma pack规定的对齐长度,实际使用的规则是:
结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
也就是说,当#pragma pack的值等于或超过所有数据成员长度的时候,这个值的大小将不产生任何效果。
而结构整体的对齐,则按照结构体中最大的数据成员 和 #pragma pack指定值 之间,较小的那个进行。
具体解释
#pragma pack(4)
class TestB
{
public:
int aa; //第一个成员,放在[0,3]偏移的位置,
char a; //第二个成员,自身长为1,#pragma pack(4),取小值,也就是1,所以这个成员按一字节对齐,放在偏移[4]的位置。
short b; //第三个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[6,7]的位置。
char c; //第四个,自身长为1,放在[8]的位置。
};
这个类实际占据的内存空间是9字节
类之间的对齐,是按照类内部最大的成员的长度,和#pragma pack规定的值之中较小的一个对齐的。
所以这个例子中,类之间对齐的长度是min(sizeof(int),4),也就是4。
9按照4字节圆整的结果是12,所以sizeof(TestB)是12。
如果
#pragma pack(2)
class TestB
{
public:
int aa; //第一个成员,放在[0,3]偏移的位置,
char a; //第二个成员,自身长为1,#pragma pack(4),取小值,也就是1,所以这个成员按一字节对齐,放在偏移[4]的位置。
short b; //第三个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[6,7]的位置。
char c; //第四个,自身长为1,放在[8]的位置。
};
//可以看出,上面的位置完全没有变化,只是类之间改为按2字节对齐,9按2圆整的结果是10。
//所以 sizeof(TestB)是10。
最后看原贴:
现在去掉第一个成员变量为如下代码:
#pragma pack(4)
class TestC
{
public:
char a;//第一个成员,放在[0]偏移的位置,
short b;//第二个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[2,3]的位置。
char c;//第三个,自身长为1,放在[4]的位置。
};
//整个类的大小是5字节,按照min(sizeof(short),4)字节对齐,也就是2字节对齐,结果是6
//所以sizeof(TestC)是6。
感谢 提出疑问,在此补充:
当数据定义中出现__declspec( align() )时,指定类型的对齐长度还要用自身长度和这里指定的数值比较,然后取其中较大的。最终类/结构的对齐长度也需要和这个数值比较,然后取其中较大的。
可以这样理解, __declspec( align() ) 和 #pragma pack是一对兄弟,前者规定了对齐的最小值,后者规定了对齐的最大值,两者同时出现时,前者拥有更高的优先级。
__declspec( align() )的一个特点是,它仅仅规定了数据对齐的位置,而没有规定数据实际占用的内存长度,当指定的数据被放置在确定的位置之后,其后的数据填充仍然是按照#pragma pack规定的方式填充的,这时候类/结构的实际大小和内存格局的规则是这样的:
在__declspec( align() )之前,数据按照#pragma pack规定的方式填充,如前所述。当遇到__declspec( align() )的时候,首先寻找距离当前偏移向后最近的对齐点(满足对齐长度为max(数据自身长度,指定值) ),然后把被指定的数据类型从这个点开始填充,其后的数据类型从它的后面开始,仍然按照#pragma pack填充,直到遇到下一个__declspec( align() )。
当所有数据填充完毕,把结构的整体对齐数值和__declspec( align() )规定的值做比较,取其中较大的作为整个结构的对齐长度。
特别的,当__declspec( align() )指定的数值比对应类型长度小的时候,这个指定不起作用。
Feedback
# re: 结构体对齐的具体含义(#pragma pack)
2005-04-03 17:17 by
已阅。
# re: 结构体对齐的具体含义(#pragma pack)
2005-04-07 08:38 by
感激,终于明白了
# re: 结构体对齐的具体含义(#pragma pack)
2005-04-07 23:10 by
# 请教一句话的翻译
2005-04-20 17:56 by
'%$S': actual alignment (%d) is greater than the value specified in __declspec(align())
请帮我看看这句话应当怎样翻,先谢过了。
“实际对齐”这种说法可以让人接受吗?
# re: susan
2005-04-21 09:17 by
实际的对齐参数比 __declspec(align())中指定的要大一些?
# 谢谢先!问号表示不确定吗?
2005-04-21 11:32 by
谢谢先!问号表示不确定吗?
# re: 结构体对齐的具体含义(#pragma pack)
2005-04-21 14:01 by
不是很确定:P
不过意思是对的啦。
# re: 结构体对齐的具体含义(#pragma pack)
2005-05-27 15:27 by
不错!
# 有一点问题
2005-06-09 19:21 by
类之间的对齐,是按照类内部最大的成员的长度,和#pragma pack规定的值之"中较小的一个对齐的。"
此结论对定义有__declspec(align(CACHE_LINE))
不成立。
#define CACHE_LINE 16
#define CACHE_ALIGN __declspec(align(CACHE_LINE))
struct S
{
char a;
CACHE_ALIGN double d;
double f;
char g;
};
# re:Michael
2005-06-09 19:54 by
__declspec( align() )是强制指定其后的类型以 指定数值 和 类型自身长度 之中的最大值来对齐。
前面的描述没有考虑这种情况。
当数据定义中出现__declspec( align() )时,指定类型的对齐长度还要用自身长度和这里指定的数值比较,然后取其中较大的。最终类/结构的长度也需要和这个数值比较,然后取其中较大的。
# re: pAnic
2005-06-10 12:51 by
You are right.
This article is good.
# re: Michael
2005-06-10 16:54 by
thanks~
# re: 结构体对齐的具体含义(#pragma pack)
2005-12-31 15:56 by
我还有个问题就是
struct a
{
int id;
char length;
char ip[16];
};
这个为什么是24
# re: 结构体对齐的具体含义(#pragma pack)
2006-06-02 11:55 by
char ip[16] 相当于 16句 char ch; ?????
这样倒是 24
# re: 结构体对齐的具体含义(#pragma pack)
2006-08-03 10:56 by
"nt aa; //第一个成员,放在[0,3]偏移的位置,
char a; //第二个成员,自身长为1,#pragma pack(4),取小值,也就是1,所以这个成员按一字节对齐,放在偏移[4]的位置。
short b; //第三个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[6,7]的位置。
char c; //第四个,自身长为1,放在[8]的位置"
那请问[5]在哪里呀?
# re: 结构体对齐的具体含义(#pragma pack)
2006-12-14 17:05 by
不能同意楼主的说法,楼住说的有问题,完全是想当然!
# re: 结构体对齐的具体含义(#pragma pack)
2007-01-17 20:51 by
//2007.1.18 字节对齐
#pragma pack(4)
typedef struct _ST001
{
int aa; //0-3
char a;//1:4 按1字节对齐,4
int b; //4:4 按4字节对齐,
char c;//2:4 按2字节对齐
}ST001;
class C001
{
public:
int aa;
char a;//1:4 按1字节对齐
int b; //4:4 按4字节对齐
char c;//2:4 按2字节对齐
};
#pragma pack()
typedef struct _ST002
{
int aa;
char a;
int b;
char c;
}ST002;
class C002
{
public:
int aa;
char a;//1:4 按1字节对齐
int b; //4:4 按4字节对齐
char c;//2:4 按2字节对齐
};
main()
{
//2007.1.18 字节对齐
printf("Struct:%d,%d\nClass:%d,%d",sizeof(ST001),sizeof(ST002),sizeof(C001),sizeof(C002));
getch();
}
输出结果:
Struct:16,16
Class:16,16
如改为#pragma pack(2)
输出结果为:
Struct:12,16
Class:12,16
测试环境:VC6,默认对齐:8
与楼主的贴子不符啊.
# re: 结构体对齐的具体含义(#pragma pack)
2007-01-17 20:53 by
汗一个.
[把本来是short的b定义成int了]
# re: 结构体对齐的具体含义(#pragma pack)
2007-03-28 13:05 by
8错 8错 长知识
# re: 结构体对齐的具体含义(#pragma pack)
2007-04-17 21:56 by
感谢楼主!
# re: 结构体对齐的具体含义(#pragma pack)
2007-05-17 17:05 by
找了好久,因为这个东东,与一个好公司错过了,早看到就好了
# fvvxdiqs
2007-08-25 20:51 by
# re: 结构体对齐的具体含义(#pragma pack)
2007-09-18 15:56 by
谢谢,很有启发
# re: 结构体对齐的具体含义(#pragma pack)
2008-02-29 10:21 by
明白了,感谢,支持 !
# hodicjcm
2009-09-08 02:36 by
# cheap fioricet adenoidectomy subrogation
2009-09-10 03:56 by
You have to have funny faces and words, you can't just have words. It is a powerful thing, and I think that's why it's hard for people to imagine that women can do that, be that powerful.
# buy adipex online
2009-09-10 03:57 by
Winning is important to me, but what brings me real joy is the experience of being fully engaged in whatever I'm doing.
# retin
2009-09-10 07:33 by
Nothing is more conducive to peace of mind than not having any opinions at all.
# finasteride
2009-09-10 10:46 by
The nice thing about egotists is that they don't talk about other people.
# generic xanax
2009-09-10 10:49 by
See things as they are and write about them. Don?t waste your creative energy trying to make things up. Even if you are writing fiction, write the things you see and know.
# alprazolam online
2009-09-10 10:50 by
Marriage is the only adventure open to the cowardly.
# generic norvasc gumbrine logician
2009-09-10 10:58 by
The only way to get rid of a temptation is to yield to it.
# cheap adipex
2009-09-10 14:59 by
Deeds, not words shall speak me.
# norvasc
2009-09-10 15:03 by
When you close your doors, and make darkness within, remember never to say that you are alone, for you are not alone; nay, God is within, and your genius is within. And what need have they of light to see what you are doing?
# awnyvfon
2009-09-10 21:39 by
# cheap levitra
2009-09-11 02:49 by
I often quote myself. It adds spice to my conversation.
# esomeprazole
2009-09-11 02:52 by
It is your work in life that is the ultimate seduction.
# esomeprazole
2009-09-11 02:53 by
Funny business, a woman's career: the things you drop on the way up the ladder so you can move faster. You forget you'll need them again when you get back to being a woman. It's one career all females have in common, whether we like it or not: being a woman. Sooner or later, we've got to work at it, no matter how many other careers we've had or wanted.
# anticollineation
2009-09-11 02:56 by
My theory of evolution is that Darwin was adopted.
# would
2009-09-11 02:56 by
If one sticks too rigidly to one's principles, one would hardly see anybody.
# lumdwbbr
2009-09-11 10:36 by
dyndnzbr
http://eengxlua.com rflfzlfo svgbjfog