内存对齐

MichaelBomb 2010-09-19 12:21:56
一。
class A
{
char c;
double b;
virtual void FuncA();
};

sizeof(A)=?

我的理解是:内存开始处存放虚函数表指针需要4个字节。
然后char c占1个字节,对齐为4。4+4=8。
最后double占8。
因此sizeof(A)=4+4+8=16,刚好是8的整数倍。因此答案为16。
可是VS2008运行结果为24。
二。
通过上述结果,我于是觉得可能虚函数表指针放在内存块的结尾处。
因此,char占1,double占8,对齐为8+8=16.结尾虚表指针占4,
总的字节为:8+8+4=20。不为8的整数倍,因此还需要再填充4个字节,结果为24.
倒是可以理解的通。
三。为了验证二的结果,就是虚表指针是否真的放在内存的结尾?
我又改变如下,
class A
{
double b;
char c;
virtual void FuncA();
};

这样的话,double 8,char 1,虚表4,前面为9需要对齐变成8+4为12.
再加上虚表的4为12+4=16.为8的整数倍,因此为16.
可是sizeof(A)=24.

所以我就糊涂了。

这个到底是怎么一个回事。大家讨论讨论,就当作复习吧。
...全文
900 40 打赏 收藏 转发到动态 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2011-02-25
  • 打赏
  • 举报
回复
不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。

不要迷信《爱情心理学》、《爱情测验题》、情场老手、情感回帖;
要迷信荷尔蒙、身体器官、身体感受、生米煮成熟饭。

(^_^)
赵4老师 2011-02-25
  • 打赏
  • 举报
回复
不要理解她,要观察她,触摸她。
VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
碎碎念 2011-02-25
  • 打赏
  • 举报
回复
我用vs2008测试了一下。。。
结果。。。
虚函数表放在类的起始处,且对齐到8字节。。。。
所以后面的c对齐到一字节,b对齐到8字节。。
sizeof(A)=8+1+7+8=24

所以
对于第二个类
sizeof(A)=8+8+1+7=24

zhiyoujinsheng 2011-02-25
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 shenchenman 的回复:]
31楼楼主说的 char按道理是应该对齐到4的。
你怎么这么应该的???谁告诉你应该对齐到4了???编译器默认8字节对齐,就算是默认4字节对齐,也是和结构体中最长的元素取大的作为对界,因为一个char+一个double大于8,所以char单独对齐,当然对齐到8了。这个有什么疑问么还?大家已经说的这么多了,楼主咋还不醒悟呢?
[/Quote]
class A
{
char c;
double b;
virtual void FuncA();
};
如果默认是4据字节对齐,char就是4,sizeof(a)=16,我刚刚测过
zhiyoujinsheng 2011-02-25
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 michaelbomb 的回复:]
还有就是,虚函数表指针都放开头,那么:
class A
{
char c;
double b;
virtual void FuncA();
};
class B
{
int a; //等同于虚表指针
char c;
double b;
};

那么,sizeof(A),与sizeof(B)结果应该是一样的。

可是运行结果 sizeof(A)……
[/Quote]
只能说你的系统默认是8字节对齐
greex 2010-09-21
  • 打赏
  • 举报
回复
这个说法是对的:
#pragma pack(4) // 字节对齐
class A
{
char c;
double b;
virtual void FuncA();
};
#pragma pack(pop)

如果不设置字节对弃,差异就大了...
MichaelBomb 2010-09-20
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 majinguang2004 的回复:]
问题的根源:
对于A:char c 对齐为8
double b 为8
虚函数指针对齐为8
总和为24
对于B:int a为4,再在剩下的四个字符中加上char 1 然后再对齐(a+c后对齐为8)
然后double b为8 总共为16

引用 10 楼 michaelbomb 的回复:
还有就是,虚函数表指针都放开头,那么:
class A
{
char c;
……
[/Quote]

虚表指针放在开头,跟所以char按道理是应该对齐到4的。
你直接说对齐到8,但是原因呢。
MichaelBomb 2010-09-20
  • 打赏
  • 举报
回复
楼上各位都没指出根源所在。
lovestefanie 2010-09-20
  • 打赏
  • 举报
回复
confused
MichaelBomb 2010-09-20
  • 打赏
  • 举报
回复
struct a
{
char a; //32楼你说的应该是这种情况
double b;
int c;
};

struct b
{
int c; //等同于虚表指针的位置
char a;
double b;
};
显然是不同的,
MichaelBomb 2010-09-20
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 shenchenman 的回复:]
31楼楼主说的 char按道理是应该对齐到4的。
你怎么这么应该的???谁告诉你应该对齐到4了???编译器默认8字节对齐,就算是默认4字节对齐,也是和结构体中最长的元素取大的作为对界,因为一个char+一个double大于8,所以char单独对齐,当然对齐到8了。这个有什么疑问么还?大家已经说的这么多了,楼主咋还不醒悟呢?
[/Quote]
虚表指针是放在表头,所以char在内存是5,对齐到8.
你说的char1 对齐到double的8的话,那是char前面没有任何东西,所以。。。
shenchenman 2010-09-20
  • 打赏
  • 举报
回复
31楼楼主说的 char按道理是应该对齐到4的。
你怎么这么应该的???谁告诉你应该对齐到4了???编译器默认8字节对齐,就算是默认4字节对齐,也是和结构体中最长的元素取大的作为对界,因为一个char+一个double大于8,所以char单独对齐,当然对齐到8了。这个有什么疑问么还?大家已经说的这么多了,楼主咋还不醒悟呢?
cswuyg 2010-09-19
  • 打赏
  • 举报
回复
VS和GCC编译器都是吧虚函数表指针放在对象的首部的。
反汇编后发现你说的问题是这样:
虚函数表指针(4)+浪费掉的(4)+ char要对齐(8)+double(8)= 24。
pengzhixi 2010-09-19
  • 打赏
  • 举报
回复
class A
{
public:
char c;
double b;
virtual void FuncA(){}
};

int _tmain(int argc, _TCHAR* argv[])
{
A obj;
cout<<(void*)&obj<<" "<<(void*)&(obj.c)<<" "<<(void*)&(obj.b)<<endl;
cout<<sizeof(A)<<endl;
system("pause");
return 0;
}
diaoni 2010-09-19
  • 打赏
  • 举报
回复
虚函数指针一般都是放开头的,如果是4byte对齐的话,应该是4+1+3+8=16,估计LZ是8byte对齐
某某9 2010-09-19
  • 打赏
  • 举报
回复
#pragma pack
diaoni 2010-09-19
  • 打赏
  • 举报
回复
这要看编译器设置是怎样的对齐方式,VC的用编译器指令试试看结果是多少:

#pragma pack(push)
#pragma pack(4) // 字节对齐
class A
{
char c;
double b;
virtual void FuncA();
};
#pragma pack(pop)
print(sizeof(A));
luzhiwei512 2010-09-19
  • 打赏
  • 举报
回复
一 你分析错了应该是4+1+3+8=16,有的编译器是看前面一个和后面的一个4+1+7+8=20+4(8n)
横云断岭 2010-09-19
  • 打赏
  • 举报
回复
虚函数表貌似是放在开头……
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 kanguolaikanguolaik 的回复:]
class A
{
char c;
double b;
virtual void FuncA();
};

本来是:
char: 1字节
double: 8字节
Virtual: 4字节
对齐后:
char: 8字节
double: 8字节
Virtual: 8字节 所以共24字节



如果改成:
class A
{
……
[/Quote]


上述回复错误:
Virtual 是单独分配内存的 不能和其他类型合并(如上面的char型)
上述sizeof(A) 永远是24
加载更多回复(20)

64,701

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧