Code Bye

关于内存对齐的一个问题

#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占用了两个字节?
解决方案

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

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个字节。
地址也符合这样的规律。

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
//
//

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明关于内存对齐的一个问题