1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该基本数据类型所整除的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为上面介绍的对齐模数。
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
备注:为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员的整数倍,若是,则存放本成员,反之,则在本成员和上一个成员之间填充一定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节(trailing padding)。
备注:结构体总大小是包括填充字节,最后一个成员满足上面两条以外,还必须满足第三条,否则就必须在最后填充几个字节以达到本条要求。
问题是:编译器为什么做这个优化,有啥好处嗯?
比如例子:
struct test
{
char m1;
double m4;
int m3;
};
15 个解决方案
#1
优化搜索速度
#2
因为cpu的最小处理单位是32位
#3
字节对齐限制简化了形成处理器和存储器系统之间接口的硬件设计,例如,假设一个处理器总是从存储器中取出8个字节,则地址必须为8的倍数,如果我们能保证将所有的double类型数据的地址对齐成8的倍数,那么就可以用一个存储器操作来读写值了,否则,我们可能需要执行两次存储器访问,则对象可能被在两个8字节存储器块中。
有些处理器指令是要求强制对齐的,任何试图以不满足对齐要求的地址来访问存储器都会导致异常的发生。如SSE指令。
有些处理器指令是要求强制对齐的,任何试图以不满足对齐要求的地址来访问存储器都会导致异常的发生。如SSE指令。
#4
节省内存 且对内存的操作简单
#5
能具体说说如何节省内存了吗?我这一点不明白。还有就是为什么结构体的总大小为结构体最宽基本类型成员大小的整数倍?同时为啥在对齐方式中如果一个结构体嵌套到另外一个结构体中,它作为整体的默认对齐方式是结构体中最大长度的对齐方式.
#6
能具体说说如何节省内存了吗?我这一点不明白。还有就是为什么结构体的总大小为结构体最宽基本类型成员大小的整数倍?同时为啥在对齐方式中如果一个结构体嵌套到另外一个结构体中,它作为整体的默认对齐方式是结构体中最大长度的对齐方式.
#7
对于结构体数据类型最这些限制 作何考虑呢》
#8
如果真感兴趣,找本书读读
深入理解计算机系统
好想 cache 有提到过 一点
深入理解计算机系统
好想 cache 有提到过 一点
#9
就是简化处理器和存储器系统之间接口的硬件设计
#10
3楼正解,竟然还有人说节省内存和catch。。。。
在32位系统下,由于总线结构是32位的,对齐的好处就是读取小于32位只用一个指令就可以把数据读出来,提高了运行效率,至于为啥最宽,这样就可以保证用最少的指令读取数据
在32位系统下,由于总线结构是32位的,对齐的好处就是读取小于32位只用一个指令就可以把数据读出来,提高了运行效率,至于为啥最宽,这样就可以保证用最少的指令读取数据
#11
这是CPU要求的
#12
了解一下数字逻辑电路?
#13
这是代码速度优化的结果
不对齐的数据加载时,需要两个以上的时钟周期,对齐只要一个
例如
int *x =(int *)0x400012 ;
*x=100; 两个以上的时钟周期
对齐的数据,int *x =(int *)0x400000;
*x =100;一个时钟周期就可以了!
不对齐的数据加载时,需要两个以上的时钟周期,对齐只要一个
例如
int *x =(int *)0x400012 ;
*x=100; 两个以上的时钟周期
对齐的数据,int *x =(int *)0x400000;
*x =100;一个时钟周期就可以了!
#14
这本书里没有介绍这个
#15
#1
优化搜索速度
#2
因为cpu的最小处理单位是32位
#3
字节对齐限制简化了形成处理器和存储器系统之间接口的硬件设计,例如,假设一个处理器总是从存储器中取出8个字节,则地址必须为8的倍数,如果我们能保证将所有的double类型数据的地址对齐成8的倍数,那么就可以用一个存储器操作来读写值了,否则,我们可能需要执行两次存储器访问,则对象可能被在两个8字节存储器块中。
有些处理器指令是要求强制对齐的,任何试图以不满足对齐要求的地址来访问存储器都会导致异常的发生。如SSE指令。
有些处理器指令是要求强制对齐的,任何试图以不满足对齐要求的地址来访问存储器都会导致异常的发生。如SSE指令。
#4
节省内存 且对内存的操作简单
#5
能具体说说如何节省内存了吗?我这一点不明白。还有就是为什么结构体的总大小为结构体最宽基本类型成员大小的整数倍?同时为啥在对齐方式中如果一个结构体嵌套到另外一个结构体中,它作为整体的默认对齐方式是结构体中最大长度的对齐方式.
#6
能具体说说如何节省内存了吗?我这一点不明白。还有就是为什么结构体的总大小为结构体最宽基本类型成员大小的整数倍?同时为啥在对齐方式中如果一个结构体嵌套到另外一个结构体中,它作为整体的默认对齐方式是结构体中最大长度的对齐方式.
#7
对于结构体数据类型最这些限制 作何考虑呢》
#8
如果真感兴趣,找本书读读
深入理解计算机系统
好想 cache 有提到过 一点
深入理解计算机系统
好想 cache 有提到过 一点
#9
就是简化处理器和存储器系统之间接口的硬件设计
#10
3楼正解,竟然还有人说节省内存和catch。。。。
在32位系统下,由于总线结构是32位的,对齐的好处就是读取小于32位只用一个指令就可以把数据读出来,提高了运行效率,至于为啥最宽,这样就可以保证用最少的指令读取数据
在32位系统下,由于总线结构是32位的,对齐的好处就是读取小于32位只用一个指令就可以把数据读出来,提高了运行效率,至于为啥最宽,这样就可以保证用最少的指令读取数据
#11
这是CPU要求的
#12
了解一下数字逻辑电路?
#13
这是代码速度优化的结果
不对齐的数据加载时,需要两个以上的时钟周期,对齐只要一个
例如
int *x =(int *)0x400012 ;
*x=100; 两个以上的时钟周期
对齐的数据,int *x =(int *)0x400000;
*x =100;一个时钟周期就可以了!
不对齐的数据加载时,需要两个以上的时钟周期,对齐只要一个
例如
int *x =(int *)0x400012 ;
*x=100; 两个以上的时钟周期
对齐的数据,int *x =(int *)0x400000;
*x =100;一个时钟周期就可以了!
#14
这本书里没有介绍这个