知识点总结——结构体大小、内存对齐方式
2016-04-01 19:27
585 查看
1.首先是各编译器下sizeof()值:
32位编译器:32位系统下指针占用4字节
char :1个字节
char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 4个字节
long long: 8个字节
unsigned long: 4个字节
64位编译器:64位系统下指针占用8字节
char :1个字节
char*(即指针变量): 8个字节
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 8个字节
long long: 8个字节
unsigned long: 8个字节
2.内存对齐方式:
引用别人的总结:“假设我们同时声明两个变量:
char a;
short b;
用&(取地址符号)观察变量a,
b的地址的话,我们会发现(以16位CPU为例):
如果a的地址是0x0000,那么b的地址将会是0x0002或者是0x0004。
那么就出现这样一个问题:0x0001这个地址没有被使用,那它干什么去了? 答案就是它确实没被使用。 因为CPU每次都是从以2字节(16位CPU)或是4字节(32位CPU)的整数倍的内存地址中读进数据的。如果变量b的地址是0x0001的话,那么CPU就需要先从0x0000中读取一个short,取它的高8位放入b的低8位,然后再从0x0002中读取下一个short,取它的低8位放入b的高8位中,这样的话,为了获得b的值,CPU需要进行了两次读操作。
但是如果b的地址为0x0002,
那么CPU只需一次读操作就可以获得b的值了。所以编译器为了优化代码,往往会根据变量的大小,将其指定到合适的位置,即称为内存对齐(对变量b做内存对齐,a、b之间的内存被浪费,a并未多占内存)。”这个人的总结点这
结构体内对齐规则:
(1)每个成员分别按自己的对齐字节数和PPB(指定的对齐字节数,32位机默认为4)两个字节数最小的那个对齐,这样可以最小化长度。如在32bit的机器上,int的大小为4,因此int存储的位置都是4的整数倍的位置开始存储。
(2)复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,结构体数组的时候,可以最小化长度。看下面例子。
(3)结构体对齐后的长度必须是成员中最大的对齐参数(PPB)的整数倍,这样在处理数组时可以保证每一项都边界对齐。
(4)结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的最大数据成员大小的整数倍开始存储。如 struct A 中包含 struct B, struct B 中包含数据成员 char, int, double,则 struct B 应该以sizeof(double)=8的整数倍为起始地址。(感觉跟2优点像,分不清)
共用体和大小端
大端模式:内存地址从低地址开始读,
小端模式:内存地址从高地址开始读。
数组地址:地址从低地址开始。
![](http://img.blog.csdn.net/20160401201742700)
这里要注意的是大小端说的是读写时按从高到低的地址(大端)顺序还是从低到高的地址顺序读写。
32位编译器:32位系统下指针占用4字节
char :1个字节
char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 4个字节
long long: 8个字节
unsigned long: 4个字节
64位编译器:64位系统下指针占用8字节
char :1个字节
char*(即指针变量): 8个字节
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 8个字节
long long: 8个字节
unsigned long: 8个字节
2.内存对齐方式:
引用别人的总结:“假设我们同时声明两个变量:
char a;
short b;
用&(取地址符号)观察变量a,
b的地址的话,我们会发现(以16位CPU为例):
如果a的地址是0x0000,那么b的地址将会是0x0002或者是0x0004。
那么就出现这样一个问题:0x0001这个地址没有被使用,那它干什么去了? 答案就是它确实没被使用。 因为CPU每次都是从以2字节(16位CPU)或是4字节(32位CPU)的整数倍的内存地址中读进数据的。如果变量b的地址是0x0001的话,那么CPU就需要先从0x0000中读取一个short,取它的高8位放入b的低8位,然后再从0x0002中读取下一个short,取它的低8位放入b的高8位中,这样的话,为了获得b的值,CPU需要进行了两次读操作。
但是如果b的地址为0x0002,
那么CPU只需一次读操作就可以获得b的值了。所以编译器为了优化代码,往往会根据变量的大小,将其指定到合适的位置,即称为内存对齐(对变量b做内存对齐,a、b之间的内存被浪费,a并未多占内存)。”这个人的总结点这
结构体内对齐规则:
(1)每个成员分别按自己的对齐字节数和PPB(指定的对齐字节数,32位机默认为4)两个字节数最小的那个对齐,这样可以最小化长度。如在32bit的机器上,int的大小为4,因此int存储的位置都是4的整数倍的位置开始存储。
(2)复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,结构体数组的时候,可以最小化长度。看下面例子。
(3)结构体对齐后的长度必须是成员中最大的对齐参数(PPB)的整数倍,这样在处理数组时可以保证每一项都边界对齐。
(4)结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的最大数据成员大小的整数倍开始存储。如 struct A 中包含 struct B, struct B 中包含数据成员 char, int, double,则 struct B 应该以sizeof(double)=8的整数倍为起始地址。(感觉跟2优点像,分不清)
struct A { char a; //内存位置: [0] double b; // 内存位置: [8]...[15] int c; // 内存位置: [16]...[19] ---- 规则1 }; // 内存大小:sizeof(A) = (1+7) + 8 + (4+4) = 24, 补齐[20]...[23] ---- 规则3 struct B { int a, // 内存位置: [0]...[3] A b, // 内存位置: [8]...[31] ---- 规则2 char c, // 内存位置: [32] }; // 内存大小:sizeof(B) = (4+4) + 24 + (1+7) = 40, 补齐[33]...[39] *注释:(1+7)表示该数据成员大小为1,补齐7位;(4+4)同理。
共用体和大小端
大端模式:内存地址从低地址开始读,
小端模式:内存地址从高地址开始读。
数组地址:地址从低地址开始。
#include<stdint.h> #include<stdio.h> union X { int32_t a; struct { int16_t b; int16_t c; }; }; int main(){ X x; x.a=0x20150810; printf("%x,%x\n",x.b,x.c); return 0; }
这里要注意的是大小端说的是读写时按从高到低的地址(大端)顺序还是从低到高的地址顺序读写。
相关文章推荐
- 中断概念
- 奇异值分解(SVD)原理详解及推导
- OleContainer操作Excel以二进制方式读写数据库
- poj 3696 The Luckiest number (数论-快速幂+欧拉定理)
- 蓝桥杯_算法提高_身份证升级(简单字符处理)
- 1467 数据结构:一元多项式加法
- redhat6.2相关配置(yum,,r,rstudio,ipythonnotebook)
- 在CocoaPod中安装BmobSDK
- 无头指针单链表删除元素
- 复制文件时,如何显示进度条(使用BlockRead函数读取数据,并插入application.ProcessMessages)
- 文件交互功能实现问题总结
- CodeForces 631E Product Sum(斜率优化DP+二分|三分)
- Service生命周期浅析 4000
- HNOI模拟赛总结
- jsp 分页条 结合page.jar 实现分页数据和分页条分离
- 1465 数据结构:有序链表的合并
- Jenkins环境搭建(1)
- 流媒体协议RTMP,RTSP与HLS有什么不同
- HDU 1232 畅通工程 并查集
- OpenGL(二)