#pragma pack(8)
#include <iostream>
using namespace std;
class A
{
public:
A(char a,short b,char c,double d):i(a),j(b),k(c),x(d){}
char i;
short j;
char k;
double x;
};
class foo
{
public:
foo(char aa,char a,short b,char c,double d):i(aa),a(a,b,c,d){}
char y;
A a;
};
int main()
{
foo f(1,2,3,4,5.0);
cout << sizeof(foo) << endl;
}
以上这段代码在查看内存的时候,为什么f.a.i和f.a.k占用了两个字节?
#include <iostream>
using namespace std;
class A
{
public:
A(char a,short b,char c,double d):i(a),j(b),k(c),x(d){}
char i;
short j;
char k;
double x;
};
class foo
{
public:
foo(char aa,char a,short b,char c,double d):i(aa),a(a,b,c,d){}
char y;
A a;
};
int main()
{
foo f(1,2,3,4,5.0);
cout << sizeof(foo) << endl;
}
以上这段代码在查看内存的时候,为什么f.a.i和f.a.k占用了两个字节?
解决方案
10
#pragma pack(8) #include <iostream> using namespace std; class A { public: A(char a, short b, char c, double d) :i(a), j(b), k(c), x(d) {} char i; short j; char k; double x; }; class foo { public: foo(char aa, char a, short b, char c, double d) :y(aa), a(a, b, c, d) {} char y; A a; }; int main() { cout << offsetof(foo, y) << endl; cout << offsetof(foo, a.i) << endl; cout << offsetof(foo, a.j) << endl; cout << offsetof(foo, a.k) << endl; cout << offsetof(foo, a.x) << endl; }
=>
0
8
10
12
16
基本类型本身多大就要求多大对齐, lz能想到一个满足要求又少内存占用的排列方法?
10
其实不是f.a.i和f.a.k占用了两个字节,而是为了满足变量f.a.j和f.a.x的内存对其要求
变量j占用两个字节,则内存对齐必须为2的倍数,变量i偏移为8,加上自身长度1,导致j的首地址为9,不满足条件,加1调整为10,造成了变量i占用两个字节的假象
变量x占用8个字节,则内存对齐必须为8的倍数,变量i偏移为12,加上自身长度1,导致j的首地址为13,不满足条件,加3调整为16,造成了变量x占用4个字节的假象
建议题主看一篇非常好的文章http://www.cnblogs.com/King-Gentleman/p/5297355.html
变量j占用两个字节,则内存对齐必须为2的倍数,变量i偏移为8,加上自身长度1,导致j的首地址为9,不满足条件,加1调整为10,造成了变量i占用两个字节的假象
变量x占用8个字节,则内存对齐必须为8的倍数,变量i偏移为12,加上自身长度1,导致j的首地址为13,不满足条件,加3调整为16,造成了变量x占用4个字节的假象
建议题主看一篇非常好的文章http://www.cnblogs.com/King-Gentleman/p/5297355.html
10
基本数据类型的大小和对齐机制和编译器有关。
在本人的编译器(g++),char占一个字节,short两个字节,double占8个字节。
依次打印foo和A的大小,以及变量地址,
一开始只有一个f.a.i,当前最大对齐值为1,占一个字节。
之后f.a.j为short,当前最大对齐值为2,而前面只有一个字节,不是2的倍数,故空一个字节再加入short。当前共占4个字节。
接下来是char, 又占了一个字节,再空一个字节,以保持当前最大对齐值2的倍数。目前共6个字节。
再下来是double, 最大对齐值为8个字节,前面的不是8的倍数,故再空2个字节,再加入double, 这样A就是16个字节。
而对于foo, 加入char y后再占一个字节,共17字节,但不是当前最大对齐值8 的倍数,故再空7个字节,这样foo就是24个字节。
地址也符合这样的规律。
在本人的编译器(g++),char占一个字节,short两个字节,double占8个字节。
依次打印foo和A的大小,以及变量地址,
一开始只有一个f.a.i,当前最大对齐值为1,占一个字节。
之后f.a.j为short,当前最大对齐值为2,而前面只有一个字节,不是2的倍数,故空一个字节再加入short。当前共占4个字节。
接下来是char, 又占了一个字节,再空一个字节,以保持当前最大对齐值2的倍数。目前共6个字节。
再下来是double, 最大对齐值为8个字节,前面的不是8的倍数,故再空2个字节,再加入double, 这样A就是16个字节。
而对于foo, 加入char y后再占一个字节,共17字节,但不是当前最大对齐值8 的倍数,故再空7个字节,这样foo就是24个字节。
地址也符合这样的规律。
10
仅供参考:
#include <stdio.h> #define field_offset(s,f) (int)(&(((struct s *)(0))->f)) struct AD { int a; char b[13]; double c;}; #pragma pack(push) #pragma pack(1) struct A1 { int a; char b[13]; double c;}; #pragma pack(2) struct A2 { int a; char b[13]; double c;}; #pragma pack(4) struct A4 { int a; char b[13]; double c;}; #pragma pack(8) struct A8 { int a; char b[13]; double c;}; #pragma pack(16) struct A16 { int a; char b[13]; double c;}; #pragma pack(pop) int main() { printf("AD.a %d\n",field_offset(AD,a)); printf("AD.b %d\n",field_offset(AD,b)); printf("AD.c %d\n",field_offset(AD,c)); printf("AD sizeof %d\n", sizeof(AD)); printf("\n"); printf("A1.a %d\n",field_offset(A1,a)); printf("A1.b %d\n",field_offset(A1,b)); printf("A1.c %d\n",field_offset(A1,c)); printf("A1 sizeof %d\n", sizeof(A1)); printf("\n"); printf("A2.a %d\n",field_offset(A2,a)); printf("A2.b %d\n",field_offset(A2,b)); printf("A2.c %d\n",field_offset(A2,c)); printf("A2 sizeof %d\n", sizeof(A2)); printf("\n"); printf("A4.a %d\n",field_offset(A4,a)); printf("A4.b %d\n",field_offset(A4,b)); printf("A4.c %d\n",field_offset(A4,c)); printf("A4 sizeof %d\n", sizeof(A4)); printf("\n"); printf("A8.a %d\n",field_offset(A8,a)); printf("A8.b %d\n",field_offset(A8,b)); printf("A8.c %d\n",field_offset(A8,c)); printf("A8 sizeof %d\n", sizeof(A8)); printf("\n"); printf("A16.a %d\n",field_offset(A16,a)); printf("A16.b %d\n",field_offset(A16,b)); printf("A16.c %d\n",field_offset(A16,c)); printf("A16 sizeof %d\n", sizeof(A16)); printf("\n"); return 0; } //AD.a 0 //AD.b 4 //AD.c 24 //AD sizeof 32 // //A1.a 0 //A1.b 4 //A1.c 17 //A1 sizeof 25 // //A2.a 0 //A2.b 4 //A2.c 18 //A2 sizeof 26 // //A4.a 0 //A4.b 4 //A4.c 20 //A4 sizeof 28 // //A8.a 0 //A8.b 4 //A8.c 24 //A8 sizeof 32 // //A16.a 0 //A16.b 4 //A16.c 24 //A16 sizeof 32 // //