首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 请教:关于内存对齐问题。请解释以下程序运行结果。 [已结帖,结帖人:happyflyingbird]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • happyflyingbird
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2008-10-30 13:58:49 楼主
    程序1:
    #include <iostream>
    using namespace std;
    class B0 //声明基类B0
    { public: //外部接口
    char nV;
    char n;
    //void fun(){cout < <"Member of B0" < <endl;}
    };
    class B1: virtual public B0 //B0为虚基类,派生B1类
    { public: //新增外部接口
    int nV1;
    };
    class B2: virtual public B0 //B0为虚基类,派生B2类
    { public: //新增外部接口
    int nV2;
    };

    class D1: public B1, public B2 //派生类D1声明
    {
    public: //新增外部接口
    int nVd;
    //void fund(){cout < <"Member of D1" < <endl;}
    };
    void main() //程序主函数
    {
    B0  b0;
    B1  b1;
    B2  b2;

    D1 d1; //声明D1类对象d1
    d1.nV=2; //使用最远基类成员
    //d1.fun();
    cout < <sizeof(B0) < <"  " < <sizeof(B1) < <"  " < <sizeof(B2) < <"  " < <sizeof(D1) < <endl;
    cout < <sizeof(b0) < <"  " < <sizeof(b1) < <"  " < <sizeof(b2) < <"  " < <sizeof(d1);



    运行结果:
    2  10  10  22
    2  10  10  22

    程序2:
    #include <iostream>
    using namespace std;
    class X1
    {
      int i;//4个字节
      char c1;//1个字节
        char c2;//1个字节
      };

    class X2
    {
      char c1;//1个字节
      int i;//4个字节
      char c2;//1个字节
    };

    class X3
    {
      char c1;//1个字节
      char c2;//1个字节
      int i;//4个字节
    };
    int main()

        cout < <"long " < <sizeof(long) < <"\n";
        cout < <"float " < <sizeof(float) < <"\n";
        cout < <"int " < <sizeof(int) < <"\n";
        cout < <"char " < <sizeof(char) < <"\n";

        X1 x1;
        X2 x2;   
    X3 x3;
        cout < <"x1 的大小 " < <sizeof(x1) < <"\n";
        cout < <"x2 的大小 " < <sizeof(x2) < <"\n";
        cout < <"x3 的大小 " < <sizeof(x3) < <"\n";
        return 0;
    }

    运行结果:
    long 4
    float 4
    int 4
    char 1
    x1 的大小 8
    x2 的大小 12
    x3 的大小 8

    在visual c++6.0中运行。
    对于程序1,由于使用virtual继承,会增加“内部调整指针”,以免使子类重复拷贝同一个数据。由此B0:2个char,2个字节;B1:BO继承来的的2个char+内部调整指针(4字节)+自身int nV1(4字节)=10字节;同理B2也是10字节;D1:从B1和B2那里来的两个“内部调整指针”(8字节)+nV1(4字节)+nV2(4字节)+nVd(4字节)=20字节,其中函数由于存放在代码区,不参与类的sizeof计算。由此好像根本没有考虑内存对齐的问题。

    对于程序2,显示考虑了内存对齐。而且好像是4字节对齐。
    但是我在project->setting->c/c++->category/code  generation->structure  member  alignment 里,无论怎么设置,结果都一样。

    不知道我上面的分析有没有错。
    到底什么时候对齐,什么时候不对齐,具体对齐是怎么个对齐法呢?迷惑中。。。。
    欢迎大家发表意见。希望了解的高手们能够抽出点点时间帮我解除疑惑,感激不尽!

    100  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • redleaves
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-30 14:08:501楼 得分:5
    所有的基本类型都有相应的对齐参数,编译器在编译时,会用全局的对齐参数和当前类型的对齐参数中较小的一个进行对齐.
    比如,编译时你指定按8字节对齐,可以你的类型是char,由于char的对齐参数是1,所以最后还是按1字节对齐.
    对于复合类型,所有的成员都按各自的对齐参数和全局对齐参数中较小的一处进行对齐.
    比如:
    struct {
    char a;
    short b;
    long c;
    }
    这个结构里,a就对齐在1字节边界,b就对齐在2字节边界,c就对齐在4字节边界.最后这个结构就占8个字节...
    对于这个结构来说,它的对齐参数则是它所有成员里最大的一个对齐参数,也就是说,这个结构在对齐的时候,就会按4字节对齐...
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • redleaves
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-30 14:15:072楼 得分:5
    还忘说了一点.
    对于上面结构来说,对齐之后还要补齐,目的就是为了在设定这个类型的数组时,所有的项都可以正确的对齐到相应的位置.
    就像你的例子里的
    class X1
    {
      int i;//4个字节
      char c1;//1个字节
      char c2;//1个字节
    };
    虽然这个结构只占了6个字节,但由于它的成员i是4字节对齐的,也就要求结构按4字节对齐,如果它sizeof是6的话,就会导致定义数组时,第二项无法对齐.所以这时编译器会给结构补两个字节.以保证结构的大小是它对齐参数的整数倍.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • xtting_8984313
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-30 14:36:403楼 得分:3
    ls说的好。
    对于第一个因为都是char,所以就不需要补齐了,只需要对齐就可以,所以为2,
    两个10增加的是一个int和一个指针(指向vtbl)(从你的结果猜测是这样)
    后面的22,因为是virtual继承,原来的两个char不变,分别增加了B1 B2 比B多的那部分就是  2+(12-2)+(12-2),可以搜索virtual 继承或者“菱形继承”
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • chenzhp
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-30 14:44:284楼 得分:10
    综上所述:

    Win32平台下的微软 编译器(cl.exe for 80×86)的对齐策略:
    1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
    备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该基本数据类型所整除的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为上面介绍的对齐模数。
    2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
    备注:为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员的整数倍,若是,则存放本成员,反之,则在本成员和上一个成员之间填充一定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。
    3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节(trailing padding)。
    备注:结构体总大小是包括填充字节,最后一个成员满足上面两条以外,还必须满足第三条,否则就必须在最后填充几个字节以达到本条要求。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Chiyer
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 4

      4

      4

    发表于:2008-10-30 22:00:005楼 得分:1
    UP
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hngsc_0
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-30 22:10:506楼 得分:2
    up
    记得c++必知必会中说过,最好保持对类实现的良好的不知情;否则用POD风格
    MARK
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zmlovelx
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-30 22:12:217楼 得分:2
    c/c++内存对齐
    http://blog.csdn.net/sharpdew/articles/772504.aspx
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zmlovelx
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-30 22:15:338楼 得分:2
    引用楼主:对于程序2,显示考虑了内存对齐。而且好像是4字节对齐。
    但是我在project->setting->c/c++->category/code  generation->structure  member  alignment 里,无论怎么设置,结果都一样

    PS:  你加个在主函数前面 #pragma pack(1)
    试试
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • leank
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 00:51:459楼 得分:3
    还有一种对齐方式,那就是强制对齐。
    强制对齐与自然对齐取小的值,就是实际对齐的方式。
    当确定实际对齐方式以后,如果在前一个成员剩余的对齐空间不足以放下该成员时,则该成员放到下一个存储空间。
    引用 4 楼 chenzhp 的回复:
    综上所述:

    Win32平台下的微软 编译器(cl.exe for 80×86)的对齐策略:
    1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
    备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该基本数据类型所整除的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为上面介绍的对齐模数。
    2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整…
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hqin6
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 00:55:4010楼 得分:1
    内存对齐,说的太多了,不想说了!

    lz看看网上的一些资料!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jia_xiaoxin
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 02:49:3911楼 得分:2
    D1:从B1和B2那里来的两个“内部调整指针”(8字节)+nV1(4字节)+nV2(4字节)+nVd(4字节)+ BO继承来的2个char = 22;

    B1和B2都重B0继承2个char,但是因为B1和B2是虚继承B0,所以,D1的父类中,会共享B0的空间,所以只从B0继承来的2个char 而不是4个。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jia_xiaoxin
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 02:54:2712楼 得分:2
    在vc6中栈的对齐方式不受结构成员对齐选项的影响。(本来就是两码事)。它总是保持对齐,而且对齐在4字节边界上。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fengogo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 03:16:1213楼 得分:3
    我的理解:为什么要内存对齐?

    CPU与内存通过地址总线与数据总线进行联系. 地址总线传输内存的地址. 假如数据总线是32位,则一次可传输4个字节数据. 虽然内存是按字节编址的, 但是其实地址总线里只会出现偶数地址(或4的倍数地址等). 所以如果一个数据的起始地址与结束地址不在(同一个)偶数地址, 那么可能就需要读取两次内存, 如果数据超过了数据总线的宽度,那肯定要读取多次内存.
    所以简单的判断方法是:
    class X1
    {
      int i;//4个字节
      char c1;//1个字节
        char c2;//1个字节
      };
    假如是4字节对齐, 即地址总线只出现4的倍数地址. 那么读取i 是读取一次内存, 读取c1与c2也是一次足够, 因为c1的地址肯定是4的倍数. 末尾补齐2字节,保证其他对象/数据 也是4字节对齐. 所以是 4 + 2 + 2 = 8字节

    class X2
    {
      char c1;//1个字节
      int i;//4个字节
      char c2;//1个字节
    };
    为了能读取一次内存就能读取到整个 i 数据, 对c1进行补齐,即c1 占了4字节, 从而使i的起始地址是4的倍数, 可直接放到地址总线.
    所以是4+4+4 = 12字节

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • happyflyingbird
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 09:28:0914楼 得分:0
    上面各位对于单独的类的内存对齐问题分析得很好很透彻。非常感谢!

    可是我对于继承的类的内存分配对齐问题仍存在疑惑。。。。

    将程序1修改如下:

    #include <iostream>
    using namespace std;
    class B0 //声明基类B0
    { public: //外部接口
    char nV;
    double n;
    //void fun(){cout < <"Member of B0" < <endl;}
    };
    class B1: virtual public B0 //B0为虚基类,派生B1类
    { public: //新增外部接口
    char i;
    int nV1;

    };
    class B2: virtual public B0 //B0为虚基类,派生B2类
    { public: //新增外部接口
    int nV2;
    };

    class D1: public B1, public B2 //派生类D1声明
    {
    public: //新增外部接口
    int nVd;
    //void fund(){cout < <"Member of D1" < <endl;}
    };
    void main() //程序主函数
    {
    B0  b0;
    B1  b1;
    B2  b2;

    D1 d1; //声明D1类对象d1
    d1.nV=2; //使用最远基类成员
    //d1.fun();
    cout < <sizeof(double) < <endl;
    cout < <sizeof(B0) < <"  " < <sizeof(B1) < <"  " < <sizeof(B2) < <"  " < <sizeof(D1) < <endl;
    cout < <sizeof(b0) < <"  " < <sizeof(b1) < <"  " < <sizeof(b2) < <"  " < <sizeof(d1) < <endl;
    printf("%p %p %p %p %p\n",&b1,&b1.i,&b1.nV1,&b1.nV,&b1.n);
    printf("%p %p %p %p %p %p %p",&d1,&d1.i,&d1.nV1,&d1.nV2,&d1.nVd,&d1.nV,&d1.n);
    }


    运行结果:
    8
    16  32  24  48
    16  32  24  48
    0012FF50 0012FF54 0012FF58 0012FF60 0012FF68
    0012FF08 0012FF0C 0012FF10 0012FF1C 0012FF20 0012FF28 0012FF30

    其中的48从何而来??
    根据第二个printf语句可以看出,D1各成员存放的顺序为:调整指针1,i,nV1,调整指针2,nV2,nVd,nV,n。
    0012FF10 0012FF1C ,nV1与nV2之间为何会相差12个字节。按道理说,相差应该是4字节nV1+4字节调整指针2=8字节而已。这样也满足对齐,由此后推,应该为:调整指针1(4字节)+i(1字节)+填充(3字节)+nV1(4字节)+调整指针(4字节)+nV2(4字节)+nVd(4字节)+nV(1字节)+填充(7字节)+n(8字节)=40字节才对啊,为何是48?

    请高手们继续解答,谢谢了!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jiju8484
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 09:53:5115楼 得分:1
    参考:
    http://super-jiju.spaces.live.com/blog/cns!806C498DDEE76B61!315.entry
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hqin6
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 09:53:5816楼 得分:2
    引用 14 楼 happyflyingbird 的回复:
    上面各位对于单独的类的内存对齐问题分析得很好很透彻。非常感谢!

    可是我对于继承的类的内存分配对齐问题仍存在疑惑。。。。

    将程序1修改如下:

    #include <iostream>
    using namespace std;
    class B0 //声明基类B0
    { public: //外部接口
    char nV;
    double n;
    //void fun(){cout < <"Member of B0" < <endl;}
    };
    class B1: virtual public B0 //B0为虚基类,派生B1类
    { public: //新增外部接口
    ch…


    lz,这默认的是八字节对齐,你可以加上下面这句试试:

    C/C++ code
    #paragma pack(4)
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • redleaves
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 10:06:1517楼 得分:3
    楼主,你用virtual继承,编译器会在对象里放一些其它的信息来保证其行为...这些东西在标准里没有规定,编译器可以对它进行任意排布.原则上,对齐只对POD类型有意义.其它类型很难保证其布局...比如:编译器甚至可以对类的私有成员进行重排...
    所以,很多时候你会发现,我们定义数据包多用使用而不是继承...
    比如:
    struct a {
      ...
    };
    struct b { //通常是这样
      a _member;
      ....
    };
    struct c : public a {  // 这样在绝大多数情况下是可以的,但不能保证
      ...
    };
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hqin6
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 11:39:1918楼 得分:3
    引用 14 楼 happyflyingbird 的回复:
    上面各位对于单独的类的内存对齐问题分析得很好很透彻。非常感谢!

    可是我对于继承的类的内存分配对齐问题仍存在疑惑。。。。

    将程序1修改如下:

    #include <iostream>
    using namespace std;
    class B0 //声明基类B0
    { public: //外部接口
    char nV;
    double n;
    //void fun(){cout < <"Member of B0" < <endl;}
    };
    class B1: virtual public B0 //B0为虚基类,派生B1类
    { public: //新增外部接口
    ch…
    C/C++ code
    看看下面就知道了: 对于D1: +--------+----------+ | VB10 | B1:i | +--------+----------+ | B1:nv1 | +-------------------+ | VB20 | B2:nv2 | +--------+----------+ | B0:nv | +-------------------+ | B0:n | +-------------------+ | D1:nvd | +-------------------+ 每一行是8字节的,因为最大的是double,八字节! 6*8 = 48 | |



    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • CHIDE
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 11:52:4619楼 得分:2
    B0:
    char nV;    8
    double n;    8
    B1:
    1个调整指针  +  char i  +  int nV1    16
    B2:
    1个调整指针  +  int nV2    8
    D1:
    int nVd;    8
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • CHIDE
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 11:57:4420楼 得分:2
    程序1:
    #include <iostream>
    using namespace std;
    class B0 //声明基类B0
    { public: //外部接口
    char nV;
    char n;
    //void fun(){cout < <"Member of B0" < <endl;}
    };
    class B1: virtual public B0 //B0为虚基类,派生B1类
    { public: //新增外部接口
    int nV1;
    };

    个人感觉sizeof(B1)应为12
    B0  2  (被继承后应该在B1里补齐为4吧
    1个调整指针  4
    int nV1    4

    4+4+4=12

    请教下,为什么B0在程序里为2而不是4
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • happyflyingbird
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 19:11:3821楼 得分:0
    感谢大家的回答。不过,以上回答都不能完全解释两个程序的结果。

    CHENZHP总结得非常到位,可是“结构体的总大小为结构体最宽基本类型成员大小的整数倍”,下面的程序都体现了这一点,不解为何最上面第一个程序在有int的情况下会出来10,22的结果。
    hqin6的回答无法解释printf得到的地址问题,没有调整指针,也无法解释修改前程序的运行结果。对了,您说的“#pragma pack(4)”用了结果还是一样的哦。怎么改都一样的。不知道了。。。
    CHIDE的回答对修改后的程序解释得有效,但无法解释上面第一个程序结果的10和22哦.
    redleaves您的回答比较有意思,“乱放的”?
    怎么总有点不对劲啊。。。

    看来俺真比较笨,头大了。。。。

    前面有几位给我提供了几个链接,我这里上网受限制都打不开,谢谢了,真不好意思哦。
    还有几位怎么是凌晨在回答哦,真是辛苦了,幸好说的不是梦话。。。


    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • baihacker
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 4

    发表于:2008-10-31 20:19:1222楼 得分:4
    10:
    指针4字节(指向一个位移信息表)
    本身数据4字节
    虚基类的数据2字节
    共10字节

    22:
    作为B1的对象,8个字节,其中4字节的指针(指向一个位移信息表),4字节的数据
    作为B2的对象,8个字节,其中4字节的指针(指向一个位移信息表),4字节的数据
    本身的数据 4字节
    虚基类的数据 2字节

    (由于这些乱七八糟的数据,大小已经不是由以前的什么对齐规则所限了)

    为什么会有一个位移信息表呢?
    注意下面的代码
    B2* p = &d1;
    p本身的的和d1的地址相等吗?
    明显不等,p指向了d1这个对象偏移八个位置的地方:即B2
    也许现在还看不出问题.
    接着:
    p->nV = 一个值;
    于是要通过这4字节的指针,得到虚基类的数据的偏移地址.

    注意到,如果p是作为B1的指针呢?
    p->nV = 一个值;
    同样需要一个偏移地址.
    两者的偏移地址区别如下.


    一个纯粹的B1对象,虚基类的数据的偏移地址为8
    一个纯粹的B2对象,虚基类的数据的偏移地址为8

    一个D1对象,虚基类的数据的偏移地址为8+8+4 = 20;
    现在d1作为一个B1对象,虚基类的数据的偏移地址为20(即,这个指针指向的表的第一项的值为20)
    现在d2作为一个B2的对象,虚基类的数据偏移地址为12(即,这个指针指向的表的第一项的值为12)

    在上面,两个纯粹的B1或B2对象的虚基类的数据偏移地址为8
    而不是纯粹的话,就可能是20,12.

    有虚函数的时候差不多.
    这也就是传说中的,有多继承,有虚基类的时候指针重设问题.

    这里只是VC6的实现,换个编译器可能有别人方案.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jeff_nie
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 21:04:2123楼 得分:1
    mark.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lzp765
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 21:44:5424楼 得分:1
    学习!~~~
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • redleaves
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-10-31 21:51:3225楼 得分:2
    引用 21 楼 happyflyingbird 的回复:
    redleaves您的回答比较有意思,“乱放的”?

    楼主有点曲解我的意思了吧...我只是说在这些未指明的情况下,编译可以按自己的想法任意排布.可不是乱放.不同的实现,就会有不同的规则...仅此而已....
    如非必要,不用去探求这种非标准化的东西.如果你真的很想了解,这也很简单,编译并生成汇编文件,你就可以看到详细的数据结构....
    修改