`
ChuanSu
  • 浏览: 53374 次
  • 性别: Icon_minigender_1
  • 来自: 石家庄
社区版块
存档分类
最新评论

C/C++ Data alignment 及 struct size深入分析

阅读更多
C语言,在对一个 struct variable使用sizeof operator(操作符)的时候,往往得到的结果并不是我们想象中——struct内所有member的size之和。

当清楚了什么是Data alignment(数据对齐),对这个问题就豁然开朗了。

Data Alignment

在C/C++,甚至所有programming language中,每个Data object,更确切的说是 每个variable都有两个属性 :
  • value (自身的值)
  • memory address(其内存地址)
对每个variable的分析,都是基于内存分析的。所以,分析variable自身value的时候,又是分析 其在内存中的存储形式.所以更确切的是
     Variable Properties 
  • bit pattern
  • memory address
往往variable最重要的属性,是其内存地址。这也是为什么 在C/C++中,指针,pointer是如此的强大。

Data Alignment 并非针对 Data 本身,而是Data(Variable)的内存地址 。在 MSDN 对 Alignment做出定义,其第一句话便是
Alignment is a property of a memory address

以一张表格来展现32-bit machine 的内存结构



计算机中,内存是由大量的,连续的,可寻址的或编了号的memory cells(内存单元)构成。每个memory cell 占1 byte。

假如上述表格 bank0的address 为X,那么bank1,bank2,bank2的地址分别为X+1,X+2,X+2。

CPU在处理内存数据时,并非一次提取一个memory cell,一般提取一组相邻内存单元。在32-bit machine,CPU一次从内存中读取 4个连续的memory cell(4-byte) 。所以在此表格中,4 byte chunk(4字节流) 为一个读取周期。在读取一个int型 数据时,仅仅需要一个周期(int 占4 byte)。读取Double型,则需要2个读取周期。表格(D0-D31,32-bit)表示一个内存周期。如果是8-bit machine 即1字长(D0-D7),则需要4个周期来读取一个integer。


说了一些基本的内存知识,接下来看看 MSDN对Alignment的定义是怎么样的
MSDN 写道

Alignment is a property of a memory address, expressed as the numeric address modulo a power of 2. For example, the address 0x0001103F modulo 4 is 3; that address is said to be aligned to 4n+3, where 4 indicates the chosen power of 2. The alignment of an address depends on the chosen power of two. The same address modulo 8 is 7.

An address is said to be aligned to X if its alignment is Xn+0.

CPUs execute instructions that operate on data stored in memory, and the data are identified by their addresses in memory.

仔细理解下,可以总结为,当向内存中放入一个数据(variable)时,此数据的地址,严格来说是offset,起始地址,必须是此数据的Alignment的整数倍。即上述 Xn+0。
对于每种类型的数据,都有其自身的Alignment

Data Type Alignments(in Bytes)
   char            1         
   short           2         
   int             4         
   float           4         
   double        4 or 8      


例如char 的offset可以在bank0,bank1,bank2,bank3任意一个(这里为了方便,假设bank0初始位置的address为0,依次类推)。short型的2 bytes只能存储在 bank0-bank1或者bank2-bank3,假如其offset在bank1上,即存储在bank1-bank2,那么此address为奇数,并非short alinment的整数倍。


int型,offset只能在bank0上,在其他位置,都不会是4的整数倍。如果一个int型的整数,0xABCDEF,在内存中的起始位置在 bank1 上会发生什么呢?



可以看到此integer的addres并非是4的整数倍,跨过两行,那么在读取此data时,就需要两个读取周期了。

所以data alignment正是用来处理variable在这些bank中的存储方式。以避免发生此情况。在上表中,此整数的地址为5,5=4n+1,按照MSDN定义来说,此整数的alignment为1.但是int 型的alignment应该是4。所以这种情况又称为misaligned

Data Structure Padding


在C/C++中,因为对variable都有alignment的要求,所以在struct中,每一个member都要遵循alignment的要求。就拿 MSDN中的一个例子,来谈下struct的alignment
struct x_
{
   char a;     // 1 byte
   int b;      // 4 bytes
   short c;    // 2 bytes
   char d;     // 1 byte
} MyStruct;


同上述表格一样,struct中的member在内存中,是由下至上allocate的。

char a的起始位置在bank0,假如addrees为0;

int b,是不可以在bank1,bank2,bank3,这样b的offset为奇数,不是4的整数倍,所以只能在bank4,其4 bytes在 bank4-bank5-bank6-bank7;

那么在char a与int b之间需要填补3个无意义的byte。来满足int b的对齐方式。

short c是可以在bank8的,8为2的整数倍。所以b,c间无需要填补。那么short c 存储在 bank8-bank9。

char d可以存储在任何位置。那么char d 则存储在 byte10.

最后需填补1 byte

padding byte   char d      short c    short c    
int b          int  b      int   b    int   b    
padding bytepadding bytepadding byte  char  a    


在最后填补一个byte的原因是:
在struct的member的alignment中,找到alignment的最大值(此处为4 bytes),在struct的最后一个member填补 padding bytes使整个struct的size 为此aligment(4 bytes)的整数倍。

所以上述struct 在内存中的实际形式为
// Shows the actual memory layout
struct x_
{
   char a;            // 1 byte
   char _pad0[3];     // padding to put 'b' on 4-byte boundary
   int b;            // 4 bytes
   short c;          // 2 bytes
   char d;           // 1 byte
   char _pad1[1];    // padding to make sizeof(x_) multiple of 4
}


此struct的size为12 bytes,而不是8 bytes。


Resource

http://msdn.microsoft.com/en-us/library/ms253949.aspx
http://en.m.wikipedia.org/wiki/Data_structure_alignment#section_5
http://www.geeksforgeeks.org/archives/9705
http://www.songho.ca/misc/alignment/dataalign.html
  • 大小: 11.2 KB
  • 大小: 4.9 KB
分享到:
评论
1 楼 NonMac 2016-09-11  
良心博客,谢谢博主~~

相关推荐

    SQLMemTable for Delphi / C++ Builder

    SQLMemTable for Delphi / C++ Builder: README============================================Please read this file carefully (especially the INSTALLATION chapter) before installing the program to your ...

    RTRV.rar_生物技术_C/C++_

    例如,使用C/C++编写的BLAST(Basic Local Alignment Search Tool)程序可以快速查找DNA或蛋白质序列中的相似片段;还有SWIG(Simplified Wrapper and Interface Generator)这样的工具,用于将C/C++代码与Python等...

    Data Alignment in SEE、SSE2

    例如,在使用Intel C/C++ Compiler和Microsoft Visual C++ Compiler共同构建应用程序时,不同编译器之间的对齐规则可能存在差异,导致程序行为不一致。 1. **混合构建应用**:在混合使用VC++和Intel C++ Compiler ...

    insightface alignment c++

    insightface c++ 人脸关键点并进行对齐矫正 code for face alignment in c++

    FaceVerification.rar_Windows编程_C/C++_

    在本文中,我们将深入探讨如何在Windows环境下使用C/C++进行人脸识别,特别是在“FaceVerification.rar”这个项目中,我们看到其主要依赖于开源的SeetaFace引擎。SeetaFace是一款强大的面部识别库,专为实时和高精度...

    生物统计,gloable alignment C程序

    《全球对齐算法在生物统计中的应用——C/C++实现》 全球对齐算法是生物信息学中的一个重要工具,主要用于序列比对,特别是在DNA、RNA和蛋白质序列分析中。这种算法的目标是找到两个或多个序列之间的最佳匹配,使得...

    Data Alignment Error(亲测可用).md

    Data Alignment Error(亲测可用).md

    opencv_3rdparty-contrib_face_alignment_20170818.zip

    本篇文章将深入探讨如何下载、编译OpenCV的Face Alignment模块,并使用CMake和Visual Studio 2019进行构建。 1. OpenCV contrib模块简介: OpenCV contrib是OpenCV主库的扩展,包含了许多先进的算法,如人脸识别、...

    C/C++数据对齐详细解析

    Data Alignment 关于数据对齐问题,现在多多少少有了一些接触,简单地说下自己的看法。 1、对齐的背景 大端和小端的问题有必要在这里介绍一下,计算机里面每个地址单元对应着一个字节,一个字节为8bit,对于位数大于...

    深入理解c/c++ 内存对齐

    内存对齐,memory alignment.为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。内存对齐...

    深入理解C/C++内存对齐

    内存对齐,memory alignment.为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。  内存...

    【C++版】Face Alignment at 3000 FPS by Regressing Local Binary Features源码下载

    【C++版】"Face Alignment at 3000 FPS by Regressing Local Binary Features"源码解析 在计算机视觉领域,人脸识别与人脸对齐是一项重要的技术,广泛应用于图像处理、视频监控、虚拟现实等多个场景。"Face ...

    Face Alignment at 3000FPS(C++版)

    Face Alignment at 3000FPS(C++版)工程配置(非Cmake),这里是配置方法:http://blog.csdn.net/duan19920101/article/details/50582249

    Assignment1_C-C++_

    1. Program.cs:这可能是C#的源代码文件,但在C/C++的上下文中,这可能是一个误标,或者项目中包含了其他语言的元素,比如使用了C#的编译器或者IDE。 2. Assignment1.csproj:这是一个Visual Studio项目文件,表明...

    PictureEx头文件

    // Signature - Identifies the GIF Data Stream // This field contains the fixed value 'GIF' char m_cVersion[3]; // Version number. May be one of the following: // "87a" or "89a" }; ...

    sublime_alignment插件

    sublime_alignment插件,解压到Data/Packages目录下即可正常使用。快捷键为CTRL+ALT+A,如果与QQ截图功能冲突,请重新配置一下快捷键。 详细说明可访问:Sublime Text 2.0技巧汇总 网址:...

    GD32F407ZET6ADC驱动例程 测试可用

    /* ADC data alignment config */ adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT); adc_data_alignment_config(ADC1,ADC_DATAALIGN_RIGHT); /* ADC scan mode function enable */ adc_special_function_...

Global site tag (gtag.js) - Google Analytics