本文章验证的问题:
类的对象在栈和堆中地址,以及成员成员变量的地址有什么规律?如果成员变量有内存对齐约束,则成员变量的地址有什么规律?
验证的结论体现的代码中。
备注:这个验证不一定正确,需要进一步验证。
#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
<>