数据对齐/内存对齐 && 数据格式

一、数据对齐/内存对齐

字、双字、四字在自然边界上不需要在内存中对齐。(什么叫做字?见第二部分)

对字、双字、四字来说,自然边界分别是偶数地址、可以被4整除的地址、可以被8整除的地址。

无论如何,为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。

原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;然而,对齐的内存仅需要一次访问。

未对齐的:一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为是未对齐的,需要两次总线周期访问内存。

对齐的:一个字起始地址是奇数但却没有跨越字边界被认为的对齐的,能够在一个总线周期中被访问。

缺省情况下,编译器默认将结构、栈中的成员数据进行内存对齐。

对齐的三个规则

1.      每个成员分别按自己的方式对齐;

2.      复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式。(相当于把复杂类型展开)

3.      对齐后的长度必须是成员中最大的对齐参数的整数倍。(保证在处理数组时每一项都边界对齐)

例子

1. 对于如下结构

struct TestStruct1
{
  char c1;
  short 2;
  char c2;
  int I;
};

假设c1的地址为0,则c1为00000000,s为00000002,c2为00000004,i为00000008。

2. 对于如下结构

struct TestStruct2
{
  char a;
  long b;
};
struct TestStruct3
{
  char c;
  TestStruct2 d;
  long long e;
};

TestStruct2中,成员a是1字节,默认按1字节对齐;成员b是4字节,默认按4字节对齐。所以sizeof(TestStruct2)为8.

TestStruct3中,成员c是按1字节对齐;d是个结构,它是8字节,但是结构的默认对齐方式是其所有成员使用的对齐参数中最大的一个,所以d是按4字节对齐;e是8字节,默认按8字节对齐。内存布局如下:(*表示空闲内存,1表示使用内存)

TestStruct3的内存布局:   1***,1***,1111,****,11111111

c        d.a       d.b             e

另:对于typedef char Array3[3],Array3这种类型的对齐方式还是按1字节对齐,而不是按它的长度。

参考:《C语言深度剖析》第3章预处理,#pragma pack

#pragma pack(n)

…//此中间的部分按指定对齐方式对齐

#pragma pack()

但是成员对齐有一个重要条件,即每个成员按自己的方式对齐。(也就是说,虽然指定了按n字节对齐,但并不是所有的成员都是以n字节对齐。)对齐规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数中的较小的一个对齐,并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节。

二、数据格式

由于是从16位体系结构扩展成32位的,Intel用术语“”(word)表示16位数据类型。因为,32位数为“双字”(double words),64位数为“四字”(quad words)。

对比——字长

每台计算机都有一个字长(word size),指明整数和指针数据的标称大小。

因为虚拟地址是以这样的一个字来编码(这句话我的理解是,字长大小的各个位通过01变化来表示虚拟地址),所以字长决定的最重要的系统参数就是虚拟地址空间的最大大小。

也就是说,对于一个字长为w位的机器而言,虚拟地址的范围为0~2^w-1,程序最多访问2^w个字节。如今大多数计算机的字长都是32位,这就限定了虚拟地址空间为4GB字节。


C声明


char


short


int


long int


long long


指针


float


double


32位机器


1


2


4


4


8


4


4


8


64位机器


1


2


4


8


8


8


4


8

可以看到,

  • 短整数分配2字节,
  • 不加限定的int为4字节,
  • “长”整数使用机器的全字长(32位为4字节,64位为8字节)。
  • ISO C99引入的“长长”整数使用8字节,即64位整数。(对于32位机器,编译器必须把这种数据类型的操作编译成执行一系列32位操作的代码。)
  • 指针,使用机器的全字长。
  • 对于浮点数,单精度和双精度分别使用4字节和8字节。

关于“字长”和“字”

字长,是指出计算机整数和指针数据的标称大小,可能是32位,也可能是64位等等;而,字指的就是16位,因为双字是32位、四字是64位。注意不要弄混“字长”和“字”的概念,“字长”的意思并不是”字“的长度,而是指计算机整数和指针数据的标称大小。

时间: 2024-10-11 05:04:17

数据对齐/内存对齐 && 数据格式的相关文章

C结构体中数据的内存对齐问题

转自:http://www.cnblogs.com/qwcbeyond/archive/2012/05/08/2490897.html 32位机一般默认4字节对齐(32位机机器字长4字节),64位机一般默认8字节对齐(64位机机器字长8字节) 1.先看下面的例子:struct A{   char c1;   int i;   short s;   int j;}a; struct B{   int i;   int j;     short s;   char c1;}b; 结构A没有遵守字节对

解析C语言结构体对齐(内存对齐问题)

C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的变量总长度要大,这是怎么回事呢? 开始学的时候,也被此类问题困扰很久.其实相关的文章很多,感觉说清楚的不多.结构体到底怎样对齐? 有人给对齐原则做过总结,具体在哪里看到现在已记不起来,这里引用一下前人的经验(在没有#pragma pack宏的情况下): 原则1.数据成员对齐规则:结构(struct或

C/C++中的内存对齐问题和pragma pack命令详解

这个内存对齐问题,居然影响到了sizeof(struct)的结果值.突然想到了之前写的一个API库里,有个API是向后台服务程序发送socket请求.其中的socket数据包是一个结构体.在发送socket之前,会检测数据的长度:服务端接收到数据后也会检测长度.如果说内存对齐问题影响到了结构体的sizeof,那么socket发送结构体的时候,是怎么发送的?发送的内容中是否包含结构体中的“空洞”?如果API库中的对齐方式没有设定,那么服务端和客户端的sizeof结果将不同,这会引起很多问题吗? 下

C/C++内存对齐 ZZ

这篇文章写得非常深入浅出.推荐.图需要到原博看. http://songlee24.github.io/2014/09/20/memory-alignment/ 下面是网易的一道笔试题:struct { uint32_t m1; char m2; } varray[2];以下哪些判断一定成立?(多选) sizeof(varray[0]) == 5 sizeof(varray[0]) == 8 (void*)&(varray[0].m1) < (void*)&(varray[0].m2

内存对齐之深度探索

编译器为什么要替我们内存对齐? 学了计算机组成原理,了解了内存的基本单元是一个字节,内存可以随机寻址,于是乎我天真的认为内存就是一个字节型的容器,基本单位是单个字节. Figure 1. 我眼中的内存空间布局 悲剧的是,内存读写的真正访问者cpu不是这么想的.cpu是根据内存访问粒度(memory access granularity,下文简写成MAG)来读取内存,MAG就是cpu一次内存访问操作的数据量,具体数值依赖于特定的平台,一般是2byte.4byte.8byte. Figure 2.

c++编程思想(三)--c++中c 续,重点sizeof和内存对齐

之前理论性的太多,下面就是代码及理论结合了 1.sizeof()是一个独立运算符,并不是函数,可以让我们知道任何变量字节数,可以顺带学一下struct,union,内存对齐 内存对齐:为了机器指令快速指向地址值,编译器内部实际上会内存对齐,怎么理解了,以struct为例 先讲一下各个变量类型内存大小 所以struct理论上是:1+2+4+4+4+8+8 = 31,但是实际是 实际大小是32(1+2+1+4)+(4+4)+8+8 然后再把int和short位置调换 实际大小是40   (1+3)+

NumPy-快速处理数据--ndarray对象--多维数组的存取、结构体数组存取、内存对齐、Numpy内存结构

本文摘自<用Python做科学计算>,版权归原作者所有. 上一篇讲到:NumPy-快速处理数据--ndarray对象--数组的创建和存取 接下来接着介绍多维数组的存取.结构体数组存取.内存对齐.Numpy内存结构 一.多维数组的存取 多维数组的存取和一维数组类似,因为多维数组有多个轴,因此它的下标需要用多个值来表示,NumPy采用组元(tuple)作为数组的下标.如二维数组需要(x, y)的元组标记一个数组元素:三维数组需要(x, y, z)的元组标记一个元素. 如下图所示,a为一个6x6的二

Delphi中的内存对齐 与 Packed关键字

以delphi为例:TTest = recordc1: char;i1: Integer;c2: char;c3: Char;end;这个结构如果用sizeof取其占用的内存大小,是多少呢,是1+4+1+1=7么,不是,是4*3 = 12; 这是因为32位编译的时候,默认结构会自动内存对齐(32bit = 4byte). 如果要想让这个结构占用7个字节的话,必须加上packed关键字.如下:TTest = packed recordc1: char;i1: Integer;c2: char;c3

内存对齐与自定义类型

一.内存对齐 (一).为什么会有内存对齐? 1.为了提高程序的性能,数据结构(尤其是栈)应该尽可能的在自然边界上对齐.原因是为了访问未对齐的内存,处理器需要进行两次访问,而访问对齐的内存,只需要一次就够了.这种方式称作"以空间换时间"在很多对时间复杂度有要求问题中,会采用这种方法. 2.内存对齐能够增加程序的可移植性,因为不是所有的平台都能随意的访问内存,有些平台只能在特定的地址处处读取内存. 一般情况下内存对齐是编译器的事情,我们不需要考虑,但有些问题还是需要考虑的,毕竟c/c++是