内存对齐方式

内存对齐方式
内存对齐方式

对齐方式

为什么会有内存对齐?

在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间;各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。在缺省情况下,C编译器为每一个变量或数据单元按其自然对界条件分配空间。

字,双字,和四字在自然边界上不需要在内存中对齐。(对字,双字,和四字来说,自然边界分别是偶数地址,可以被4整除的地址,和可以被8整除的地址。)无论如何,为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。

一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为是未对齐的,从而需要两次总线周期来访问内存。一个字起始地址是奇数但却没有跨越字边界被认为是对齐的,能够在一个总线周期中被访问。

某些操作双四字的指令需要内存操作数在自然边界上对齐。如果操作数没有对齐,这些指令将会产生一个通用保护异常(#GP)。双四字的自然边界是能够被16整除的地址。其他的操作双四字的指令允许未对齐的访问(不会产生通用保护异常),然而,需要额外的内存总线周期来访问内存中未对齐的数据。

影响结构体的sizeof的因素:

1)不同的系统(如32位或16位系统):不同的系统下int等类型的长度是变化的,如对于16位系统,int的长度(字节)为2,而在32位系统下,int的长度为4;因此如果结构体中有int等类型的成员,在不同的系统中得到的sizeof值是不相同的。

2)编译器设置中的对齐方式:对齐方式的作用常常会让我们对结构体的sizeof 值感到惊讶,编译器默认都是8字节对齐。

对齐:

为了能使CPU对变量进行高效快速的访问,变量的起始地址应该具有某些特性,即所谓的“对齐”。例如对于4字节的int类型变量,其起始地址应位于4字节边界上,即起始地址能够被4整除。变量的对齐规则如下(32位系统)

理解结构体的对齐方式有点挠头,如果结构体中有结构体成员,那么这是一个递归的过程。对齐方式影响结构体成员在结构体中的偏移设编译器设定的最大对齐字节边界数为n,对于结构体中的某一成员item,一个成员的地址必须安排在成员的尺寸的整数倍地址上或者是n的整数倍地址上,取它们中的最小值,也就是它相对于结构首地址的实际字节对齐数目X应该满足以下规则:

X = min (n, sizeof (item))

实际上,1字节边界对齐也就表示了结构成员之间没有空洞。

例如,对于结构体:

struct {char a; int b} T;

当位于32位系统,n=8时:a的偏移为0,b的偏移为4,中间填充了3个字节, b 的X为4;

当位于32位系统,n=2时:a的偏移为0,b的偏移为2,中间填充了1个字节,b 的X为2;

字节对齐的细节和具体编译器实现相关,但一般而言,满足三个准则:

1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;

2) 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;例如上面第二个结构体变量的地址空间;

3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。

例如1:32位系统,n=8,

结构体struct {char a; char b;} T;

struct {char a; int b;} T1;

struct {char a; int b;char c;} T2;

sizeof(T) = 2; N = 1 没有填充;

sizeof(T1) = 8; N = 4 中间填充了3字节

sizeof(T2)=12;N = 4 中间,结尾各填充了3字节

例如2:

struct S1{char a; long b;};

struct S2 {char c; struct S1 d; long long e;};

sizeof(S2)=24;

分析:

根据上面的分析sizeof(s1)=8; S2 中c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4。所以,成员d就是按4字节对

齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除,这样一共使用了24个字节。

例如3::

Typedef struct student {

Char name[10];

Long sno;

Char sex;

Float score [4]; } STU1;

Typedef struct student {

Char name[10];

Char sex;

Long sno;

Float score [4]; } STU2;

sizeof(STU1)=10+2+4+1+3+16

sizeof(STU2)=10+2+4+16

注意:

1)对于空结构体,sizeof=1;因为必须保证结构体的每一个实例在内存中都有独一无二的地址。

2)结构体的静态成员不对结构体的大小产生影响,因为静态变量的存储位置与结构体的实例地址无关。

例如:struct {static int I;} T;

struct {char a; static int I;} T1;

sizeof(T) == 1;

sizeof(T1) == 1;

3) 某些编译器支持扩展指令设置变量或结构的对齐方式,如VC,详见MSDN (alignment of structures)

如何避免内存对齐的影响

效果:既达到提高性能的目的,又能节约一点空间。

改变缺省的对界条件:

Win32平台下的微软C编译器:

1. #pragma pack([n])

在编译时使用命令行参数#pragma pack ([n])伪指令允许你选择编译器为数据分配空间所采取的对界策略,指令语法如下:

#pragma pack ([show] | [push | pop] [, identifier], n)

#pragma pack(push) //保存对齐状态

#pragma pack(1)//设定为1字节对齐

struct foo_pack{char c1;

short s;

char c2;

int i;};

#pragma pack(pop)//恢复对齐状态

栈内存对齐:

我们可以观察到,在vc6中栈的对齐方式不受结构成员对齐选项的影响。(本来就是两码事)。它总是保持对齐,而且对齐在4字节边界上。

2. 使用c/c++中的对齐选项

Linux下的GCC:

_attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。

_attribute_ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

内存对齐方式

对齐方式 为什么会有内存对齐? 在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间;各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。在缺省情况下,C编译器为每一个变量或数据单元按其自然对界条件分配空间。 字,双字,和四字在自然边界上不需要在内存中对齐。(对字,双字,和四字来说,自然边界分别是偶数地址,可以被4整除的地址,和可以被8整除的地址。)无论如何,为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。 一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为是未对齐的,从而需要两次总线周期来访问内存。一个字起始地址是奇数但却没有跨越字边界被认为是对齐的,能够在一个总线周期中被访问。 某些操作双四字的指令需要内存操作数在自然边界上对齐。如果操作数没有对齐,这些指令将会产生一个通用保护异常(#GP)。双四字的自然边界是能够被16整除的地址。其他的操作双四字的指令允许未对齐的访问(不会产生通用保护异常),然而,需要额外的内存总线周期来访问内存中未对齐的数据。 影响结构体的sizeof的因素: 1)不同的系统(如32位或16位系统):不同的系统下int等类型的长度是变化的,如对于16位系统,int的长度(字节)为2,而在32位系统下,int的长度为4;因此如果结构体中有int等类型的成员,在不同的系统中得到的sizeof值是不相同的。 2)编译器设置中的对齐方式:对齐方式的作用常常会让我们对结构体的sizeof 值感到惊讶,编译器默认都是8字节对齐。 对齐: 为了能使CPU对变量进行高效快速的访问,变量的起始地址应该具有某些特性,即所谓的“对齐”。例如对于4字节的int类型变量,其起始地址应位于4字节边界上,即起始地址能够被4整除。变量的对齐规则如下(32位系统)

Word教程:段落格式设置:首行左右悬挂缩进及五种对齐方式

Word教程:段落格式设置:首行左右悬挂缩进及五种对齐方 式 嗨,各位亲,见面么么哒~~~前面的课程中李老师带大家学习了一个重要的知识点:Word文本格式的设置。相信各位小伙伴们都已经学会了吧?但是你知道吗?一个常规文 件的制作,除了要用到文本格式的设置外,段落格式的设置也很重要哦~~~那今天李老师就带大家学习文件制作中另一个重要的知识点——Word段落格式设置。一起来学习吧!一、Word常规段落格式设置要学习段落的格式,首先我们要明白一个问题:什么是段落?直观的讲,在WORD中,有弯箭头标志的就是一个段落。如下图:怎么产生一个段落呢?很简单,敲键盘上的“ENTER”键就可以了!说到这里,有的伙伴可能有问题:为什么我的文档中没有这个段落标记呢?好吧,这就是我们今天要学习的第一个操作:段落标记的显示和隐藏。显示段落标记操作:执行文件?选项?显示,勾选“段落标记”就可以了。如下图隐藏段落标记操作:在上图中取消段落标记的勾选即可。好,明白了段落的概念了以后,接下来我们就来学习段落的常规格式设置。1.Word段落对齐段落的对齐方式包括5种:左对齐、居中、右对齐、两端对齐、分散对齐。设置方法有以下三种:(1)利用“开始”选项卡“段落”功能区中的对齐按钮进行对齐操作。(2)利

用段落对话框进行对齐操作。单击“段落”功能区右下角的按钮,弹出段落对话框,在对话框中可以进行对齐操作。(3)利用快捷键进行Word对齐操作。a)Word左对齐快捷键:CTRL+Lb)Word居中快捷键:CTRL+Ec)Word右对齐快捷键:CTRL+Rd)Word两端对齐快捷键:CTRL+Je)Word分散对齐快捷键:CTRL+SHIFT+J2.Word段落缩进缩进?听起来很诡异的样子,呵呵……简单说来,缩进可以控制段落中的文本与正文边框之间的距离。“呃?”又出现了一个新名词,正文边框?是咩东东?看下图:看到了吗?工作区中的那个虚线框就是正文边框。它可是今天的小助教哦,能帮助大家更直观地了解段落缩进的作用。各位小伙伴的工作区里面一般都不显示正文边框的,我们可以把它显示出来。执行:文件?选项?高级,勾选“显示正文边框”,就OK啦!好,准备工作都做好了以后,我们再来看这个:小伙伴们看懂了吗?Word段落缩进分成左缩进、右缩进、首行缩进、悬挂缩进四种。左、右缩进控制的是整个段落的左边和右边;首行缩进控制的是段落第一行的文本;悬挂缩进控制的是段落除第一行外的其它行。Word段落缩进的设置方法:(1)右击鼠标,选择“段落”命令,打开段落对话框,进行设置。(2)利用标尺:拖动标尺上相应的缩进控制块就可以了!

《第八课 设置段落的对齐方式》教学设计

《第八课设置段落的对齐方式》教学设计 一、教材分析 段落的对齐方式是排版打印必须考虑的问题。按照中文的行文格式一般正文应该首行空两个格、两端对齐、标题应居中,这是学生应该重点掌握的内容。左对齐教材虽然没有讲,但也应该让学生掌握,特别是左对齐与两端对齐的效果,不仔细看没有明显的区别,学生不易理解。所以本课的重难点确定如下: 重点:首行缩进、两端对齐和居中。 难点:左对齐与两端对齐的区别。 分散对齐,在中文写作中用的不多,让学生了解就可以了。文章的用途不同,选择的对齐方式就不同,所以每种对齐方式会产生什么效果,还是应该让学生实际试一试,看一看。对不同的对齐方式有所了解,在 以后使用时才知道应该选用哪种对齐方式。 教材中是以工具栏的使用为主来传授知识的,是对大多数学生的普遍要求。对于程度较好的学生,应该学 会利用菜单来设置文章的对齐方式。 二、学生分析 通过前面几课的学习,学生已经认识了Word,会在Word中写文章。可以对文字进行删除、移动、复制等编辑操作和改变字体、字号、字型等文字格式的操作。段落格式的设置,上一节才刚刚接触,所以头脑中对段落格式设置的知识印象不深。但是对齐方式的设置,与上一节左右缩进的设置方法基本相同,只是选择的工具不同,所以可以通过知识的迁移,来学习Word中段落格式的设置,把学习新知识变成对旧知识 的迁移,这样就容易多了。 三、教学目标 知识与技能目标:了解文字的对齐方式的种类,能熟练进行相应的设置操作。 过程与方法目标:通过实际操作,对学生进行动手能力、探知能力的培养。 情感态度与价值观目标:让学生体验Word的文字处理的强大功能与魅力,提高审美能力。 四、教学准备 硬件资源准备:多媒体教学网络教室。 软件资源准备;Offfice2000办公软件,教室中没有多媒体的,可以安装Net meeting通讯工具,用它的的 共享桌面功能进行教学演示。 素材资源准备:Word文本文件:《悯农》或一篇段落较多的文章。 五、教学过程 教学建议 由于段落的对齐方式设置与缩进的设置方法相同,建议借鉴上一节课段落缩进方式的设置方法,以研究性学习为主。由学生和教师共同提出问题,教师和学生借鉴以往的经验,研究探索一种对齐方式的设置。然后学生充分运用教学资源,小组协作或自主探究,通过知识的迁移来学习其它几种段落对齐方式的设置。 (一)情景导入激发兴趣 教师出示一篇没有进行格式设置的文章(全部左对齐,没有首行缩进并且很宽)请学生进行左右缩进设置 和首行缩进设置,并且边演示边叙述操作步骤。 提问学生:调整段落缩进方式时,应注意什么问题?怎样把标题放在行的中间?学生可能会用空格键把标题居中也可能直接说出用居中按钮,这样就可以进入新课了。调整段落的缩进方式时,要把插入条(即光标)定位在当前段,这也是设置对齐方式要注意的问题。也为新课的学习扫清了障碍。 (二)任务驱动明确问题 把标题放在中间,除了用空格键还有没有更好的办法呢?我们完全可以通过设置它的对齐方式来实现。 任务1:设置标题居中。 任务2:设置段落两端对齐。 任务3:设置段落右对齐。

内存字节对齐

1.内存字节对齐和小端模式: /* 本程序是关于:编译器内存的字节对齐方式和存储时的小端对齐模式(win7 32bit) #pragma pack(n) 默认为8字节对齐,(即n=8)其中n的取值为1,2,4,8,16,32等 内存字节对齐大小和方式: 1)结构体内变量对齐: 每个变量的对齐字节数大小argAlignsize=min(#pragma pack(n),sizeof(变量)); 方式:结构体的第一个变量的初始偏移地址为0,其它变量的偏移地址(当前变量的起始地址)必须是argAlignsize的整数倍,不够整数倍的补空,不添加任何数据 2)结构体对齐: 结构体的对齐字节数大小strAlignsize=min(#pragma pack(n),sizeof(所有变量中最大字节的变量)) 方式: A.对于单独的结构体来说,结构体本身按照strAlignsize大小来对齐 B.结构体B在结构体A中时,结构体B的起始地址是结构体B的 strAlignsize大小的整数倍 小端对齐模式: 指针指着一个存储空间,存储空间地址由低到高的存储内容为:0x78,0x67,0x33,0x45 若指针为char,则获取的数据为0x78 若指针为short,则获取的数据为0x6778 若指针为long,则获取的数据为0x45336778 */ #include using namespace std; /*更改C编译器内存的缺省字节对齐方式,由默认的n=4字节,变为n字节对齐,其中n的取值为1,2,4,8,16,32等*/ #pragma pack(2) struct A { unsigned char a; unsigned short b; }; struct B { unsigned char c; unsigned int d;

寄存器sse2指令集

sse2指令集 1移动指令: 1. Movaps movaps XMM,XMM/m128 movaps XMM/128,XMM 把源存储器内容值送入目的寄存器,当有m128时,必须对齐内存16字节,也就是内存地址低4位为0. 2. Movups movups XMM,XMM/m128 movaps XMM/128,XMM 把源存储器内容值送入目的寄存器,但不必对齐内存16字节 3. Movlps movlps XMM,m64 把源存储器64位内容送入目的寄存器低64位,高64位不变,内存变量不必对齐内存16字节4. Movhps movhps XMM,m64 把源存储器64位内容送入目的寄存器高64位,低64位不变,内存变量不必对齐内存16字节. 5. Movhlps movhlps XMM,XMM 把源寄存器高64位送入目的寄存器低64位,高64位不变. 6. Movlhps movlhps XMM,XMM 把源寄存器低64位送入目的寄存器高64位,低64位不变. 7. movss movss XMM,m32/XMM 原操作数为m32时:dest[31-00] <== m32 dest[127-32] <== 0 原操作数为XMM时: dest[31-00] <== src[31-00] dest[127-32]不变 8. movmskpd movmskpd r32,XMM 取64位操作数符号位 r32[0] <== XMM[63] r32[1] <== XMM[127] r32[31-2] <== 0

9. movmskps movmskps r32,XMM 取32位操作数符号位 r32[0] <== XMM[31] r32[1] <== XMM[63] r32[2] <== XMM[95] r32[3] <== XMM[127] r32[31-4] <== 0 10. pmovmskb pmovmskb r32,XMM 取16位操作数符号位具体操作同前 r[0] <== XMM[7] r[1] <== XMM[15] r[2] <== XMM[23] r[3] <== XMM[31] r[4] <== XMM[39] r[5] <== XMM[47] r[6] <== XMM[55] r[7] <== XMM[63] r[8] <== XMM[71] r[9] <== XMM[79] r[10] <== XMM[87] r[11] <== XMM[95] r[12] <== XMM[103] r[13] <== XMM[111] r[14] <== XMM[119] r[15] <== XMM[127] r[31-16] <== 0 11. movntps movntps m128,XMM m128 <== XMM 直接把XMM中的值送入m128,不经过cache,必须对齐16字节. 12. Movntpd movntpd m128,XMM m128 <== XMM 直接把XMM中的值送入m128,不经过cache,必须对齐16字节. 13. Movnti movnti m32,r32 m32 <== r32 把32寄存器的值送入m32,不经过cache. 14. Movapd movapd XMM,XMM/m128 movapd XMM/m128,XMM 把源存储器内容值送入目的寄存器,当有m128时,必须对齐内存16字节 15. Movupd movupd XMM,XMM/m128 movapd XMM/m128,XMM 把源存储器内容值送入目的寄存器,但不必对齐内存16字节. 我感觉这两条指令同movaps 和movups 指令一样,不过又不确定. 16. Movlpd movlpd XMM,m64 movlpd m64,XMM 把源存储器64位内容送入目的寄存器低64位,高64位不变,内存变量不必对齐内存16字节

WORD文档段落属性设置常数一览

WORD文档段落属性设置常数一览 编辑:madmlwt 一、段落对齐方式Alignment 属性常量及赋值一览 常量名称描述赋值 wdAlignParagraphCenter居中 1 wdAlignParagraphDistribute分散对齐 4 wdAlignParagraphJustify等同效果左对齐 3 wdAlignParagraphJustifyHi等同效果左对齐7 wdAlignParagraphJustifyLow等同效果左对齐8 wdAlignParagraphJustifyMed等同效果左对齐 5 wdAlignParagraphLeft左对齐(两端对齐) 0 wdAlignParagraphRight右对齐 2 wdAlignParagraphThaiJustify等同效果左对齐9 说明 由于您选择或安装的语言支持(例如,英语(美国))不同,上述部分常量可能无法使用。 二、应用实例 把WORD文档的第一段落(标题)进行格式(字体和对齐)设置。 1.直接在WORD文档中应用 Sub 段落设置() With ActiveDocument.Paragraphs(1).Range .Bold = True '将标题设为粗体 .ParagraphFormat.Alignment = wdAlignParagraphCenter '标题居中 https://www.360docs.net/doc/088119097.html, = "隶书" '标题字体 .Font.Size = 18 '标题字号

End With End Sub 2.在EXCEL中操作WORD文档 Sub 段落设置() Application.ScreenUpdating = False '关闭屏幕刷新 dqM = ThisWorkbook.Path & "\操作WORD表格.doc" '要打开的WORD文件Set wdWORD = CreateObject("Word.Application") '定义一个Word对象变量Set wdDOC = wdWORD.Documents.Open(dqM) '创建文档对象 With wdWORD With .ActiveDocument.Paragraphs(1).Range'确定第一个段落对象 .Font.Size = 18 '字号 https://www.360docs.net/doc/088119097.html, = "隶书" '字体 .Font.Bold = True '加粗 .ParagraphFormat.Alignment = 1 '水平居中 End With .ActiveDocument.SaveAs'保存修改 .Quit '关闭窗口 End With Set wdDOC = Nothing '释放存储空间 Set wdWORD = Nothing '释放存储空间 Application.ScreenUpdating = False '关闭屏幕刷新 End Sub 说明: 本代码采用后期绑定,不必在对象库中去勾选Microsoft Word 11.0 Object Library对象。所以段落的水平居中代码用值1替代了wdAlignParagraphCenter 常量。 下一篇请关注《WORD 文档内置属性设置常数一览》

内存对齐

C语言内存对齐 分类:C/C++2012-04-05 20:54 1070人阅读评论(1) 收藏举报语言c编译器平台oo 首先由一个程序引入话题: 1//环境:vc6 + windows sp2 2//程序1 3 #include 4 5using namespace std; 6 7struct st1 8 { 9char a ; 10int b ; 11short c ; 12 }; 13 14struct st2 15 { 16short c ; 17char a ; 18int b ; 19 }; 20 21int main() 22 { 23 cout<<"sizeof(st1) is "<

程序的输出结果为: sizeof(st1) is 12 sizeof(st2) is 8 问题出来了,这两个一样的结构体,为什么sizeof的时候大小不一样呢? 本文的主要目的就是解释明白这一问题。 内存对齐,正是因为内存对齐的影响,导致结果不同。 对于大多数的程序员来说,内存对齐基本上是透明的,这是编译器该干的活,编译器为程序中的每个数据单元安排在合适的位置上,从而导致了相同的变量,不同声明顺序的结构体大小的不同。 那么编译器为什么要进行内存对齐呢?程序1中结构体按常理来理解sizeof(st1)和sizeof(st2)结果都应该是7,4(int) + 2(short) + 1(char) = 7 。经过内存对齐后,结构体的空间反而增大了。 在解释内存对齐的作用前,先来看下内存对齐的规则: 1、对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据成员的偏移量必须是min(#pragma pack()指定的数,这个数据成员的自身长度) 的倍数。 2、在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。 #pragma pack(n) 表示设置为n字节对齐。VC6默认8字节对齐 以程序1为例解释对齐的规则:

C语言内存字节对齐规则20180718

C语言内存字节对齐规则 在C语言面试和考试中经常会遇到内存字节对齐的问题。今天就来对字节对齐的知识进行小结一下。 首先说说为什么要对齐。为了提高效率,计算机从内存中取数据是按照一个固定长度的。以32位机为例,它每次取32个位,也就是4个字节(每字节8个位,计算机基础知识,别说不知道)。字节对齐有什么好处?以int型数据为例,如果它在内存中存放的位置按4字节对齐,也就是说1个int的数据全部落在计算机一次取数的区间内,那么只需要取一次就可以了。如图a-1。如果不对齐,很不巧,这个int数据刚好跨越了取数的边界,这样就需要取两次才能把这个int的数据全部取到,这样效率也就降低了。 图:a-1 图:a-2 内存对齐是会浪费一些空间的。但是这种空间上得浪费却可以减少取数的时间。这是典型的一种以空间换时间的做法。空间与时间孰优孰略这个每个人都有自己的看法,但是C 语言既然采取了这种以空间换时间的策略,就必然有它的道理。况且,在存储器越来越便宜的今天,这一点点的空间上的浪费就不算什么了。 需要说明的是,字节对齐不同的编译器可能会采用不同的优化策略,以下以GCC为例讲解结构体的对齐. 一、原则: 1.结构体内成员按自身按自身长度自对齐。

自身长度,如char=1,short=2,int=4,double=8,。所谓自对齐,指的是该成员的起始位置的内存地址必须是它自身长度的整数倍。如int只能以0,4,8这类的地址开始 2.结构体的总大小为结构体的有效对齐值的整数倍 结构体的有效对齐值的确定: 1)当未明确指定时,以结构体中最长的成员的长度为其有效值 2)当用#pragma pack(n)指定时,以n和结构体中最长的成员的长度中较小者为其值。 3)当用__attribute__ ((__packed__))指定长度时,强制按照此值为结构体的有效对齐值 二、例子 1) struct AA{ //结构体的有效对齐值为其中最大的成员即int的长度4 char a; int b; char c; }aa 结果,sizeof(aa)=12 何解?首先假设结构体内存起始地址为0,那么地址的分布如下 0 a 1 2 3 4 b 5 b 6 b 7 b 8 c 9 10 11 char的字对齐长度为1,所以可以在任何地址开始,但是,int自对齐长度为4,必须以4的倍数地址开始。所以,尽管1-3空着,但b也只能从4开始。再加上c后,整个结构体的总长度为9,结构体的有效对齐值为其中最大的成员即int的长度4,所以,结构体的大小向上扩展到12,即9-11的地址空着。 2) //结构体的有效对齐值为其中最大的成员即int的长度4 struct AA{ char a; char c; int b; }aa sizeof(aa)=8,为什么呢 0 a 1 c

C语言内存对齐

解析C语言结构体对齐(内存对齐问题) C语言结构体对齐也是老生常谈的话题了。基本上是面试题的必考题。内容虽然很基础,但一不小心就会弄错。写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的变量总长度要大,这是怎么回事呢? 开始学的时候,也被此类问题困扰很久。其实相关的文章很多,感觉说清楚的不多。结构体到底怎样对齐? 有人给对齐原则做过总结,具体在哪里看到现在已记不起来,这里引用一下前人的经验(在没有#pragma pack宏的情况下): 原则1、数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。 原则2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。) 原则3、收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。 这三个原则具体怎样理解呢?我们看下面几个例子,通过实例来加深理解。 例1:struct { short a1; short a2; short a3; }A; struct{ long a1; short a2; }B; sizeof(A) = 6; 这个很好理解,三个short都为2。 sizeof(B) = 8; 这个比是不是比预想的大2个字节?long为4,short为2,整个为8,因为原则3。 例2:struct A{ int a; char b; short c; }; struct B{ char b; int a; short c; }; sizeof(A) = 8; int为4,char为1,short为2,这里用到了原则1和原则3。 sizeof(B) = 12; 是否超出预想范围?char为1,int为4,short为2,怎么会是12?还是原则1和原则3。

C语言结构体对齐

C语言结构体对齐 C语言结构体对齐也是老生常谈的话题了。基本上是面试题的必考题。内容虽然很基础,但一不小心就会弄错。写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的变量总长度要大,这是怎么回事呢? 开始学的时候,也被此类问题困扰很久。其实相关的文章很多,感觉说清楚的不多。结构体到底怎样对齐? 有人给对齐原则做过总结,具体在哪里看到现在已记不起来,这里引用一下前人的经验(在没有#pragma pack宏的情况下): 原则1、数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。 原则2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b 里有char,int,double等元素,那b应该从8的整数倍开始存储。) 原则3、收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。 这三个原则具体怎样理解呢?我们看下面几个例子,通过实例来加深理解。 例1:struct { short a1; short a2; short a3; }A; struct{ long a1; short a2; }B; sizeof(A) = 6; 这个很好理解,三个short都为2。 sizeof(B) = 8; 这个比是不是比预想的大2个字节?long为4,short为2,

最全word2010教程共五部分段落设置

第三部分:段落设置 3.1对齐方式 我们在使用Word2010编辑文档的过程中,经常需要为一个或多个段落设置该段文字在页面中的对齐方式。本文就为大家介绍一下设置段落对齐方式。 段落对齐方式设置 方法一 打开Word2010文档页面,选中一个或多个段落。 在“段落”中可以选择“左对齐”、“居中对齐”、“右对齐”、“两端对齐”和“分散对齐”选项之一,以设置段落对齐方式。 方法二 打开Word2010文档页面,选中一个或多个段落。

在“段落”中单击“显示‘段落’对话框”按钮。 在“段落”对话框中单击“对齐方式”下三角按钮,在列表中选择符合我们实际需求的段落对齐方式,并单击“确定”按钮使设置生效。

3.2段落缩进 核心提示:在Word 2010中,我们可以设置整个段落向左或者向右缩进一定的字符,这一技巧在排版时经常会使用到,例如我们可以在缩进的位置,通过插入文本框,来放置其他的内容,在Word中,我们可以通过两种方法设置段落缩进。

在Word 2010中,我们可以设置整个段落向左或者向右缩进一定的字符,这一技巧在排版时经常会使用到,例如我们可以在缩进的位置,通过插入文本框,来放置其他的内容,在Word中,我们可以通过两种方法设置段落缩进。 方法1: 1、选中要设置缩进的段落,【右键】【段落】,打开段落选项卡。 2、在“缩进和间距”选项卡,设置段落缩进就可以了。 方法2: 在水平标尺上,有四个段落缩进滑块:首行缩进、悬挂缩进、左缩进以及右缩进。按住鼠标左键拖动它们即可完成相应的缩进,如果要精确缩进,可在拖动的同时按住Alt键,此时标尺上会出现刻度。 常见问题: 1、Word里段落设置是首行缩进2字符,实际却缩进了4个英语字母的位置,这是怎么回事呢? 答:缩进二个字符,是针对中文而言的,相当于英文的4个字符。 2、Word里的项目编号比段落要缩进两个字怎么操作? 答:单击符号时会出现虚线吧,选中符号,然后把最上方的标尺向右移两个字就可以了,或者按照常规的方法,在【段落】中设置。

C语言结构体的字节对齐及指定对齐方式

内存中结构体的内存对齐 一、字节对齐作用和原因: 对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐,其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit 数据,显然在读取效率上下降很多。 二、字节对齐规则: 四个重要的概念: 1.数据类型自身的对齐值:对于char型的数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4个字节。 2.结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。 3.指定对齐值:#pragma pack (value)时指定的对齐value。 4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。补充: 1).每个成员分别按自己的方式对齐,并能最小化长度。 2).复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度。 3).对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐。 #pragma pack(1) struct test { static int a; //static var double m4; char m1; int m3; } #pragma pack() //sizeof(test)=13;

内存对齐方法及原理

首先由一个程序引入话题: 1//环境:vc6 + windows sp2 2//程序1 3#include 4 5usingnamespace std; 6 7struct st1 8{ 9char a ; 10int b ; 11short c ; 12}; 13 14struct st2 15{ 16short c ; 17char a ; 18int b ; 19}; 20 21int main() 22{ 23cout<<"sizeof(st1) is "<

sizeof(st1) is 12 sizeof(st2) is 8 问题出来了,这两个一样的结构体,为什么sizeof的时候大小不一样呢? 本文的主要目的就是解释明白这一问题。 内存对齐,正是因为内存对齐的影响,导致结果不同。 对于大多数的程序员来说,内存对齐基本上是透明的,这是编译器该干的活,编译器为程序中的每个数据单元安排在合适的位置上,从而导致了相同的变量,不同声明顺序的结构体大小的不同。 那么编译器为什么要进行内存对齐呢?程序1中结构体按常理来理解sizeof(st1)和sizeof(st2)结果都应该是7,4(int) + 2(short) + 1(char) = 7 。经过内存对齐后,结构体的空间反而增大了。 在解释内存对齐的作用前,先来看下内存对齐的规则: 1、对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据成员的偏移量必须是min(#pragma pack()指定的数,这个数据成员的自身长度) 的倍数。 2、在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。 #pragma pack(n) 表示设置为n字节对齐。VC6默认8字节对齐 以程序1为例解释对齐的规则: St1 :char占一个字节,起始偏移为0 ,int占4个字节,min(#pragma pack()指定的数,这个数据成员的自身长度) = 4(VC6默认8字节对齐),所以int按4字节对齐,起始偏移必须为4的倍数,所以起始偏移为4,在char后编译器会添加3个字节的额外字节,不存放任意数据。short占2个字节,按2字节对齐,起始偏移为8,正好是2的倍数,无须添加额外字节。到此规则1的数据成员对齐结束,此时的内存状态为: oxxx|oooo|oo

a段落对齐方式和行间距等一

1、设置下面段落格式为左右各缩进1字符,右对齐 这几天心里颇不宁静。今晚在院子里坐着乘凉,忽然想起日日走过的荷塘,在这满月的月光里,总该另有一番样子吧。月亮渐渐地升高了,墙外马路上孩子们的欢笑,已经听不见了;妻在屋里拍着闰儿,迷迷糊糊地哼着眠歌。我悄悄地披了大衫,带上门出去。 2、设置下面段落格式为左右各缩进2字符,居中对齐 这几天心里颇不宁静。今晚在院子里坐着乘凉,忽然想起日日走过的荷塘,在这满月的月光里,总该另有一番样子吧。月亮渐渐地升高了,墙外马路上孩子们的欢笑,已经听不见了;妻在屋里拍着闰儿,迷迷糊糊地哼着眠歌。我悄悄地披了大衫,带上门出去。 3、设置下面段落格式为左右各缩进2磅,左对齐 这几天心里颇不宁静。今晚在院子里坐着乘凉,忽然想起日日走过的荷塘,在这满月的月光里,总该另有一番样子吧。月亮渐渐地升高了,墙外马路上孩子们的欢笑,已经听不见了;妻在屋里拍着闰儿,迷迷糊糊地哼着眠歌。我悄悄地披了大衫,带上门出去。 4、设置下面段落段前间距为2行,段后间距为0.5行,行局为20磅 这几天心里颇不宁静。今晚在院子里坐着乘凉,忽然想起日日走过的荷塘,在这满月的月光里,总该另有一番样子吧。月亮渐渐地升高了,墙外马路上孩子们的欢笑,已经听不见了;妻在屋里拍着闰儿,迷迷糊糊地哼着眠歌。我悄悄地披了大衫,带上门出去。 5、设置下面段落段后间距为1.5行,首行缩进2字符,左对齐 这几天心里颇不宁静。今晚在院子里坐着乘凉,忽然想起日日走过的荷塘,在这满月的月光里,总该另有一番样子吧。月亮渐渐地升高了,墙外马路上孩子们的欢笑,已经听不见了;妻在屋里拍着闰儿,迷迷糊糊地哼着眠歌。我悄悄地披了大衫,带上门出去。 6、设置下面段落悬挂缩进2字符,右对齐 这几天心里颇不宁静。今晚在院子里坐着乘凉,忽然想起日日走过的荷塘,在这满月的月光里,总该另有一番样子吧。月亮渐渐地升高了,墙外马路上孩子们的欢笑,已经听不见了;妻在屋里拍着闰儿,迷迷糊糊地哼着眠歌。我悄悄地披了大衫,带上门出去。

内存对齐

最近被面试了,打击挺大,问啥啥不会。 举一个很多不会的题中的一个,关于内存对齐的问题,以前也知道点,个人感觉很重要,在这里与同道中人分享下: 很多书籍中都讲到:内存可以看成一个byte数组,我们通过编程语言提供的工具对这个'大数组'中的每个元素进行读写,比如在C中我们可以用指针一次读写一个或者更多个字节,这是我们一般程序员眼中的内存样子。但是从机器角度更具体的说从CPU角度看呢,CPU发出的指令是一个字节一个字节读写内存吗?答案是'否'。CPU是按照'块(chunk)'来读写内存的,块的大小可以是2bytes, 4bytes, 8bytes, 16bytes甚至是32bytes. 这个CPU访问内存采用的块的大小,我们可以称为'内存访问粒度'。 程序员眼中的内存样子: --------------------------------- | | | | | | | | | | | | | | | | | --------------------------------- 0 1 2 3 4 5 6 7 8 9 A B C D E F (地址) CPU眼中的内存样子:(以粒度=4为例) --------------------------------------------- | | | | | | | | | | | | | | | | | | | | --------------------------------------------- 0 1 2 3 4 5 6 7 8 9 A B C D E F (地址) 有了上面的概念,我们来看看粒度对CPU访问内存的影响。 假设这里我们需要的数据分别存储于地址0和地址1起始的连续4个字节的存储器中,我们目的是分别读取这些数据到一个4字节的寄存器中, 如果'内存访问粒度'为1,CPU从地址0开始读取,需要4次访问才能将4个字节读到寄存器中; 同样如果'内存访问粒度'为1,CPU从地址1开始读取,也需要4次访问才能将4个字节读到寄存器中;而且对于这种理想中的''内存访问粒度'为1的CPU,所有地址都是'aligned address'。 如果'内存访问粒度'为2,CPU从地址0开始读取,需要2次访问才能将4个字节读到寄存器中;每次访存都能从'aligned address'起始。 如果'内存访问粒度'为2,CPU从地址1开始读取,相当于内存中数据分布在1,2,3,4三个地址上,由于1不是'aligned address',所以这时CPU要做些其他工作,由于这四个字节分步在三个chunk上,所以CPU需要进行三次访存操作,第一次读取chunk1(即地址0,1上两个字节,而且仅仅地址1上的数据有用),第二次读取chunk2(即地址2,3上两个字节,这两个地址上的数据都有用),最后一次读取chunk3(即地址5,6上两个字节,而且仅仅地址5上的

内存对齐规则

C语言中内存对齐规则讨论(struct) (2012-02-17 17:51:17) 转载▼ 分类:学习 标签: struct union c语言 内存 it 对齐: 现代计算机中内存空间都是按着byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就是需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。 对齐的作用: 各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存储。其他平台可能没有这种情况,但是最常见的是如果不按照合适其平台的要求对数据进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶数地址开始,如果一个int型(假设为32位)如

果存放在偶数开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次独处的结果的高低字节进行拼凑才能得到该int数据。显然在读取效率上下降很多。 对齐的实现 通常我们写程序的时候,不需要考虑对齐问题,编译器会替我们选择适合目标平台的对齐策略。当然,我们也可以通知给编译器传递预编译指令而改变对制定数据的对齐方法。缺省情况下,编译器为结构体的每个成员按其自然対界条件分配空间。各个成员按照他们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。自然対界即默认对齐方式,是指按结构体的成员中size最大的成员对齐。 最常见的就是struct数据结构的sizeof的结果出乎意料。 结构体的sizeof的值并不是简单的将其中各个元素所占的字节相加,而是要考虑到存储空间的字节对齐问题 结构体默认的字节对齐准则: 1.结构体变量的首地址能够被其最宽基本类型成员的大 小所整除;

GCC下结构体内存对齐问题

引言:结构对齐的目的是为了加快CPU取数据时的速度,不同的编译器有不同的标准,有关于4字节对齐的,也有关于8字节对齐的,解题时需跟据环境具体分析。 环境:ubuntu10.10 gcc 判断结构大小,只需要注意两点即可: 1.分析结构成员: 小于4字节的结构成员,相对起始地址要在成员大小的倍数上 Char 1 char 类型可以从任何地址开始 Short 2 short 类型需要相对结构起始地址以2 的倍数处开始 Int 4 大于4 4 对齐如double 大小为8字节,只需按4字节对齐即可 2.整个结构要关于最大的成员大小对齐(不大于4) 如果结构最大的成员是short 那么结构的大小应是2 的倍数,(不足时在结构末尾补足)如果最大成员是int ,则应是4 的倍数。 如果是double ,则是4 的倍数。 为什么是4 的倍数? 这是GCC默认的对齐大小,可以修改。VC下应该默认是8。 测试,以下结构的大小是? struct com { char c1; 1字节由下面的对齐知道占用了4 字节 long tt; 关于4 字节对齐占用了4 字节 int c9; 关于4 字节对齐占用了4 字节 short c3; 关于2 字节对齐占用了4 字节 double c4; 关于4字节对齐占用了8 字节 }; 4 的倍数,所以大小共24 字节。 struct T { char a; double b; }; struct TT { short a; char b; short aa; }; struct A

char c; double d; short s; char sf[5]; }; struct B { short s; char sf[5]; char c; double d; }; struct C { char c; short s; char sf[5]; double d; }; struct D { double d; char sf[5]; short s; char c; }; struct E { char c; char sf[5]; double d; short s; };

内存对齐问题的完美解释

解析C语言中的sizeof 一、sizeof的概念 sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等。它并不是函数。sizeof操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。 二、sizeof的使用方法 1、用于数据类型 sizeof使用形式:sizeof(type) 数据类型必须用括号括住。如sizeof(int)。 2、用于变量 sizeof使用形式:sizeof(var_name)或sizeof var_name 变量名可以不用括号括住。如sizeof (var_name),sizeof var_name等都是正确形式。带括号的用法更普遍,大多数程序员采用这种形式。 注意:sizeof操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。 如sizeof(max)若此时变量max定义为int max(),sizeof(char_v) 若此时char_v定义为char char_v [MAX]且MAX未知,sizeof(void)都不是正确形式。 三、sizeof的结果 sizeof操作符的结果类型是size_t,它在头文件 中typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。 1、若操作数具有类型char、unsigned char或signed char,其结果等于1。 ANSI C正式规定字符类型为1字节。 2、int、unsigned int 、short int、unsigned short 、long int 、unsigned long 、float、double、long double类型的sizeof 在ANSI C 中没有具体规定,大小依赖于实现,一般可能分别为2、2、2、2、4、4、4、8、

相关文档
最新文档