版权归原作者所有,如有侵权,请联系我们

[科普中国]-数据结构对齐

科学百科
原创
科学百科为用户提供权威科普内容,打造知识科普阵地
收藏

数据结构对齐是代码编译后在内存的布局与使用方式。包括三方面内容:数据对齐数据结构填充(padding)与包入(packing)。

简介现代计算机一般是32比特或64比特地址对齐,如果要访问的变量没有对齐,可能会触发总线错误。

当数据小于计算机的字(word)尺寸,可能把几个数据元素放在一个字中,称为包入(packing)。

许多编程语言自动处理数据结构对齐。Ada语言,PL/I,Pascal,某些C语言与C++实现,D语言,Rust,与汇编语言允许特别控制对齐的方式。1

定义内存地址a被称为n字节对齐,当a是n的倍数(n应是2的幂)。

一次内存访问被称为对齐的,当被访问的数据长度为n字节且该数据地址为n字节对齐。如果内存未对齐,称作misaligned。显然,字节访问总是对齐的。

内存指针是对齐的,如果它所指的数据是对齐的。指向聚合数据(aggregate data,如struct或数组)是对齐的,当且仅当它的每个组成数据是对齐的。1

x86体系结构x86体系架构最初是不要求内存对齐。一些SSE2指令要求数据是128比特(16字节)对齐。有些CPU指令用于未对齐访问如MOVDQU。读写内存操作仅在对齐时才是原子的。2

C语言struct在x86上的对齐C语言数据结构内的成员先后顺序不能改变。

常见的C语言编译器在32比特x86上,double是8字节对齐,但Linux上是4字节对齐(编译选项-malign-double实现8字节对齐)。

一些编译器(Microsoft,Borland,GNU,等等)使用#pragmadirective指定对齐的包入(packing)。例如:

#pragma pack(push) /* push current alignment to stack */#pragma pack(1) /* set alignment to 1 byte boundary */struct MyPackedData{ char Data1; long Data2; char Data3;};#pragma pack(pop) /* restore original alignment from stack */这个结构在32位系统的大小为6字节。2

缺省packing与#pragma packMicrosoft编译器的项目缺省packing(编译选项/Zp)与#pragma pack指令。#pragma pack指令仅能减少packing尺寸。2

数组步长数组步长(stride of an array,也称increment, pitch或step size)是程序设计时,相邻数组元素在内存中的开始地址的距离,度量单位可以是字节或者数组元素个数。步长不可小于数组元素的尺寸,但可以大于,表示有填充的字节。

数组步长如果等于数组元素的尺寸,则数组在内存中是连续的。这可称为单位步长(unit stride)。非单位步长适用于二维数组或多维数组。2

类型双关类型双关是计算机科学的术语,指任何编程技术能颠覆或者绕过一门程序设计语言的类型系统,以达成在形式语言内部难以甚至不可能实现的效果。

C语言与C++语言,语法结构如类型转换与union,以及C++增加的reinterpret_cast运算符,用于实现类型双关。

Pascal语言使用records与variants来按照多种方法处理特定数据类型。2

本词条内容贡献者为:

王慧维 - 副研究员 - 西南大学