注:以下内容选自cs:app
在linux系统沿用的策略是2字节数据类型(如short)的地址必须是2的倍数,而较大的数据类型(如int,int*,float和double)的地址必须是4的倍数。注意,这个要求意味着一个short类型的对象的地址最低位必须等于0。类似地,任何int类型的对象或指针的地址的最低两位必须都是0.
在Microsoft Windows对齐的要求更加严格----任何K直接基本对象的地址都必须是K的倍数,K=2,4,或8。特别地,它要求一个double和long long类型数据的地址应该是8的倍数。
举例说明Microsoft Windows中数据的对齐方式:
struct {
char *a;
short b;
double c;
char d;
float e;
char f;
long long g;
void *h;
}foo;
问题:
1.这个结构体中所有字段的字节偏移量是多少?
2.这个结构体的大小是多少?
3.重新排列这个结构体中的字段,以最小化浪费的空间,然后再给出重排过的结构体的字节偏移量和总大小。
解答1:
说明:g的偏移量为28+4是因为g变量大小为8字节,故其地址必须是8的倍数,但是28不是8的倍数故向后扩张为32成为8的倍数
解答2:
说明:
填充1:在偏移为28的地方存放变量g,因为g是8字节对齐,地址必须是8的倍数,28不是8的倍数,故向后便宜4个字节
填充2:结构的大小要满足是结构体成员中最大变量的整数倍,所以结构体必须的填充4字节来满足8字节对齐要求
解答3:
当所有的结构体数据元素的长度是2的幂的时候,一种行之有效的策略就是按照大小的降序排列结构体的元素。
struct {
double c;
long long g;
float e;
char *a;
void *h;
short b;
char d;
char f;
};
上述的试验在vs2010中进行的调试,代码如下:
#include <stdio.h>
#include <conio.h>
#include <iostream>
using namespace std;
typedef struct {
char *a;
short b;
double c;
char d;
float e;
char f;
long long g;
void *h;
}foo;
typedef struct {
long long g;
double c;
float e;
void *h;
char *a;
short b;
char f;
char d;
}foo2;
int main()
{
foo temp;
//printf("%d\n",sizeof(foo));
//cout<<sizeof(foo)<<endl;
cout<<"foo:"<<sizeof(foo)<<endl;
cout<<"a:"<<(size_t)(&(((foo *)0)->a))<<endl;
cout<<"b:"<<(size_t)(&(((foo *)0)->b))<<endl;
cout<<"c:"<<(size_t)(&(((foo *)0)->c))<<endl;
cout<<"d:"<<(size_t)(&(((foo *)0)->d))<<endl;
cout<<"e:"<<(size_t)(&(((foo *)0)->e))<<endl;
cout<<"f:"<<(size_t)(&(((foo *)0)->f))<<endl;
cout<<"g:"<<(size_t)(&(((foo *)0)->g))<<endl;
cout<<"h:"<<(size_t)(&(((foo *)0)->h))<<endl;
cout<<"foo2:"<<sizeof(foo2)<<endl;
cout<<"a:"<<(size_t)(&(((foo2 *)0)->a))<<endl;
cout<<"b:"<<(size_t)(&(((foo2 *)0)->b))<<endl;
cout<<"c:"<<(size_t)(&(((foo2 *)0)->c))<<endl;
cout<<"d:"<<(size_t)(&(((foo2 *)0)->d))<<endl;
cout<<"e:"<<(size_t)(&(((foo2 *)0)->e))<<endl;
cout<<"f:"<<(size_t)(&(((foo2 *)0)->f))<<endl;
cout<<"g:"<<(size_t)(&(((foo2 *)0)->g))<<endl;
cout<<"h:"<<(size_t)(&(((foo2 *)0)->h))<<endl;
getch();
return 0;
}
运行结果: