类的对象在栈和堆中地址,以及成员成员变量的地址有什么规律?

 

本文章验证的问题:

类的对象在栈和堆中地址,以及成员成员变量的地址有什么规律?如果成员变量有内存对齐约束,则成员变量的地址有什么规律?

验证的结论体现的代码中。

备注:这个验证不一定正确,需要进一步验证。

#include <iostream>
/**
 * 总结:注意以下总结都是测试出来的,还有看到具体文档的描述
 * 1、double a的地址是是64对齐,这个初始偏移是相对与test实例化的对象地址。
 * 2、如果在栈上,test对象的地址应该是struct size的倍数,因为我们成员变量里面含有64对齐,如果test对象是64的倍数,则double a加上64倍数的偏移,在全局栈中仍是64的倍数。
 * 3、如果在堆上,test对象的地址没有明确的限制。猜测:__attribute__((aligned(64)))影响的范围只能在编译期,而堆上操作都是运行期执行的,因此,__attribute__((aligned(64)))不会起作用。
 *    但是double a的地址相对于test对象的首地址仍然是偏移的64。但是从全局的堆中看,可能是不满足64的倍数的。《在堆上的的合理解释,需要查看有没有类似书籍更科学的描述》
 * 4、类的内存布局应该就是在编译器就确定了,可以参考&((datax*)0)->c,获取偏移的方式。<这个需要从具体文档中再次验证>
 * 
 * 遗留问题:
 * 1、多次尝试test在栈上对象的地址,都是128的倍数。故总结的第2条,但是也可能不对,需要进一步研究。
*/
class test
{
    public:
    test()
    {
        b = 2;
        a = 0;
    }
    int b;
    __attribute__((aligned(64))) double a;
};

 struct data
{
    int a    __attribute__( ( aligned ( 4 ) ) ) ; 
} ;
 struct datax
{
    int a    __attribute__( ( aligned ( 4 ) ) ) ;
    int c    __attribute__( ( aligned ( 128 ) ) ) ;   
} ;

int main()
{   

    test t;
    std::cout<<"-------------------t-------------------------"<<std::endl;
    std::cout<<"&t应该为128的倍数(这里非常注意,自然对齐的概念or其他的,这里需要详细研究), &t.a与&t差值应该是64的倍数,成员变量对齐方式的改变test的size会发生变化"<<std::endl;
    std::cout<<"&t: "<<&t<<"  &t.b: "<<&t.b<<"  &t.a: "<<&t.a<<"  sizeof(test):"<<sizeof(test)<<std::endl; 
    std::cout<<"-------------------t-------------------------"<<std::endl;
    
    std::cout<<std::endl;

    test* pt = new test();
    std::cout<<"-------------------pt-------------------------"<<std::endl;
    std::cout<<"t在堆中的地址随意, &t.a与&t差值应该是64的倍数"<<std::endl;
    std::cout<<"&t: "<<pt<<"  &t.b: "<<&pt->b<<"  &t.a: "<<&pt->a<<std::endl;
    std::cout<<"-------------------pt-------------------------"<<std::endl;

    std::cout<<std::endl;

    data da;
    std::cout<<"-------------------da-------------------------"<<std::endl;
    std::cout<<"&da应该为4的倍数(), &da.a与&da差值应该是4的倍数"<<std::endl;
    std::cout<<"&da: "<<&da<<"  &da.a: "<<&da.a<<std::endl;
    std::cout<<"-------------------da-------------------------"<<std::endl;

    std::cout<<std::endl;

    data da1;
    std::cout<<"-------------------da1-------------------------"<<std::endl;
    std::cout<<"&da1应该为4的倍数(), &da1.a与&da差值应该是4的倍数"<<std::endl;
    std::cout<<"&da1: "<<&da1<<"  &da1.a: "<<&da1.a<<std::endl;
    std::cout<<"-------------------da1-------------------------"<<std::endl;

    std::cout<<std::endl;

    datax dax;
    std::cout<<"-------------------dax-------------------------"<<std::endl;
    std::cout<<"&dax应该为256的倍数(这里非常注意,自然对齐的概念or其他的,这里需要详细研究), &dax.c与&dax差值应该是128的倍数,成员变量对齐方式的改变test的size会发生变化"<<std::endl;
    std::cout<<"&dax: "<<&dax<<"  &dax.a: "<<&dax.a<<"  &dax.c: "<<&dax.c<<"   sizeof(datax): "<<sizeof(datax)<<" sizeof(dax.c): "<<sizeof(dax.c)<<std::endl;
    std::cout<<"-------------------dax-------------------------"<<std::endl;

    std::cout<<std::endl;

    datax* pdax = new datax();
    std::cout<<"-------------------pdax-------------------------"<<std::endl;
    std::cout<<"pdax在堆中应该没有地址限制, &pdax.c与pdax差值应该是128的倍数"<<std::endl;
    std::cout<<"&pdax: "<<pdax<<"  &pdax.a: "<<&pdax->a<<"  &pdax.c: "<<&pdax->c<<"   sizeof(datax): "<<sizeof(datax)<<" sizeof(dax.c): "<<sizeof(dax.c)<<std::endl;
    std::cout<<"-------------------pdax-------------------------"<<std::endl;

    std::cout<<std::endl;

    std::cout<<"对象的内存布局应该是在编译期确定的,原因如下:"<<std::endl;
    std::cout<<"&((datax*)0)->c: "<<&((datax*)0)->c<<std::endl;

    return 0;
}

运行结果

-------------------t-------------------------
&t应该为128的倍数(这里非常注意,自然对齐的概念or其他的,这里需要详细研究), &t.a与&t差值应该是64的倍数,成员变量对齐方式的改变test的size会发生变化
&t: 0x7ffe8d6ea200  &t.b: 0x7ffe8d6ea200  &t.a: 0x7ffe8d6ea240  sizeof(test):128
-------------------t-------------------------

-------------------pt-------------------------
t在堆中的地址随意, &t.a与&t差值应该是64的倍数
&t: 0x11a9030  &t.b: 0x11a9030  &t.a: 0x11a9070
-------------------pt-------------------------

-------------------da-------------------------
&da应该为4的倍数(), &da.a与&da差值应该是4的倍数
&da: 0x7ffe8d6ea1e8  &da.a: 0x7ffe8d6ea1e8
-------------------da-------------------------

-------------------da1-------------------------
&da1应该为4的倍数(), &da1.a与&da差值应该是4的倍数
&da1: 0x7ffe8d6ea1ec  &da1.a: 0x7ffe8d6ea1ec
-------------------da1-------------------------

-------------------dax-------------------------
&dax应该为256的倍数(这里非常注意,自然对齐的概念or其他的,这里需要详细研究), &dax.c与&dax差值应该是128的倍数,成员变量对齐方式的改变test的size会发生变化
&dax: 0x7ffe8d6ea280  &dax.a: 0x7ffe8d6ea280  &dax.c: 0x7ffe8d6ea300   sizeof(datax): 256 sizeof(dax.c): 4
-------------------dax-------------------------

-------------------pdax-------------------------
pdax在堆中应该没有地址限制, &pdax.c与pdax差值应该是128的倍数
&pdax: 0x11a90c0  &pdax.a: 0x11a90c0  &pdax.c: 0x11a9140   sizeof(datax): 256 sizeof(dax.c): 4
-------------------pdax-------------------------

对象的内存布局应该是在编译期确定的,原因如下:
&((datax*)0)->c: 0x80

<>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值