免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2570 | 回复: 9
打印 上一主题 下一主题

c++对象的内存布局。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-05-19 21:45 |只看该作者 |倒序浏览
如下代码:

  1. class A {
  2. public:
  3.     int a;
  4.     char x;
  5. };

  6. class B : public A {
  7. public:
  8.     char y;
  9. };

  10. class C : public B {
  11. public:
  12.     char z;
  13. };

  14. int main() {
  15.     cout << sizeof(A) << sizeof(B) << sizeof(C) << endl;
  16.     return 0;
  17. }
复制代码

我测试了一下,32位机上,结果为 8,12,12.
肯定涉及到内存对齐的问题。但为什么B和C对象的大小是一样的呢?从内存上来看,这三者对象的数据成员是怎放置的?

[ 本帖最后由 disheng727 于 2009-5-19 21:49 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-05-19 21:47 |只看该作者
编译器相关问题!

论坛徽章:
0
3 [报告]
发表于 2009-05-19 21:52 |只看该作者
原帖由 system888net 于 2009-5-19 21:47 发表
编译器相关问题!

一句话 说的我没话说。看样子,这问题不值得深究。

论坛徽章:
0
4 [报告]
发表于 2009-05-19 22:27 |只看该作者
原帖由 disheng727 于 2009-5-19 21:52 发表

一句话 说的我没话说。看样子,这问题不值得深究。

g++ -S

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
5 [报告]
发表于 2009-05-19 22:38 |只看该作者

回复 #1 disheng727 的帖子

为什么总是有人对这个感兴趣 ……
#include <assert.h>
#include <string.h>

class A {
public:
    int a;
    char x;
};

class B : public A {
public:
    char y;
};

class C : public B {
public:
    char z;
};


typedef struct A_layout {
    int a;
    char x;
    static void test() {
        A a = A();
        a.a = 1212;
        a.x = 'a';
        A_layout layout = A_layout();
        memcpy(&layout,&a,sizeof(layout));
        assert(a.a==layout.a);
        assert(a.x==layout.x);
    }
private:
    static const char assume[];
} A_layout;
const char A_layout::assume[sizeof(A_layout)==sizeof(A)?1:-1] = {0};

typedef struct B_layout {
    union
    {
        A_layout inheritedA;
        struct
        {
            int a;
            char x;
        };
    };
    char y;
    static void test() {
        B b = B();
        B_layout layout = B_layout();
        test_layout(b,layout);

        b.a = 1212;
        b.x = 'a';
        b.y = 'b';
        test_layout(b,layout);
    }
private:
    static void test_union(const B_layout& layout) {
        assert(&layout.a==&layout.inheritedA.a);
        assert(layout.a==layout.inheritedA.a);
        assert(&layout.x==&layout.inheritedA.x);
        assert(layout.x==layout.inheritedA.x);
    }
    static void test_layout(const B& b,B_layout& layout) {
        test_union(layout);
        memcpy(&layout,&b,sizeof(layout));
        test_union(layout);
        assert(b.a==layout.a);
        assert(b.x==layout.x);
        assert(b.y==layout.y);
    }
    static const char assume[];
} B_layout;
const char B_layout::assume[sizeof(B_layout)==sizeof(B)?1:-1] = {0};

typedef struct C_layout {
    union
    {
        B_layout inheritedB;
        struct
        {
            union
            {
                A_layout inheritedA;
                struct
                {
                    int a;
                    char x;
                };
            };
            char y;
        };
    };
    char z;

    static void test() {
        C c = C();
        C_layout layout = C_layout();
        test_layout(c,layout);

        c.a = 1212;
        c.x = 'a';
        c.y = 'b';
        c.z = 'c';
        test_layout(c,layout);
    }
private:
    static void test_layout(const C& c,C_layout& layout) {
        test_union(layout);
        memcpy(&layout,&c,sizeof(layout));
        test_union(layout);
        assert(c.a==layout.a);
        assert(c.x==layout.x);
        assert(c.y==layout.y);
        assert(c.z==layout.z);
    }
    static void test_union(const C_layout& layout) {
        assert(&layout.y==&layout.inheritedB.y);
        assert(layout.y==layout.inheritedB.y);

        assert(&layout.x==&layout.inheritedB.x);
        assert(layout.x==layout.inheritedB.x);
        assert(&layout.x==&layout.inheritedA.x);
        assert(layout.x==layout.inheritedA.x);

        assert(&layout.a==&layout.inheritedB.a);
        assert(layout.a==layout.inheritedB.a);
        assert(&layout.a==&layout.inheritedA.a);
        assert(layout.a==layout.inheritedA.a);
    }
    static const char assume[];
} C_layout;
const char C_layout::assume[sizeof(C_layout)==sizeof(C)?1:-1] = {0};

int main() {
    A_layout::test();
    B_layout::test();
    C_layout::test();
#if defined(_MSC_VER) && _MSC_VER<1400
// msvc6 don't support omit return in main.
    return 0;
#endif
}




很无聊 ……

论坛徽章:
0
6 [报告]
发表于 2009-05-20 08:13 |只看该作者
不是不值得深究,是一般人深究不起

论坛徽章:
0
7 [报告]
发表于 2009-05-20 08:45 |只看该作者
我觉的A因为第一个是int 所以4个字节,接下去是char,要跟int对齐,所以总共8字节~~~

B和C中的char都跟int对齐~~~~ 结果就~~~~ 呵呵 不知道理解的对不~~~~~~

论坛徽章:
0
8 [报告]
发表于 2009-05-20 13:42 |只看该作者
强烈要求大牛跳出来指点!!!

论坛徽章:
0
9 [报告]
发表于 2009-05-20 13:48 |只看该作者
内存对齐问题要深究东西多了去了……

论坛徽章:
0
10 [报告]
发表于 2009-05-21 11:57 |只看该作者

回复 #1 disheng727 的帖子

2楼、6楼、9楼正解。
5楼的好长,一会再看。(饭点快到了,饭先

具体还要看编译器采用的行为。但按楼主给出的例子反向猜测对应的编译器的行为,大致是这样的,7楼说的前半段,然后B中的内存布局大概如下:
(+:表示一个字节的有效存储;*:表示一个字节的空闲填充)
int a     ++++
char x   +***
char y   +***

这个时候,C的z和B的y同为char,而且y后面有一个以上char长度的空余,所以就被补充到空余中去,变成如下:
int a        ++++
char x      +***
char y,z   ++**

如果C的z是short,而不是char的话,那是
++++
+***
+*++
还是
++++
+***
+***
++**
就好研编译器的具体行为了。

楼主不妨将整个内存区域全部置0x00,然后,对乘员填充标志性非0数值,然后dump对应的内存空间查看。

PS:
这也是在网络通信中,设计2进制的通讯协议结构所需要小心的地方之一。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP