C字节对齐

合集下载

c语言字节对齐原理

c语言字节对齐原理

c语言字节对齐原理C语言中的字节对齐原理是指在内存中分配变量存储空间时,为了提高访问效率和内存利用率,系统会按照一定的规则进行对齐操作。

字节对齐原理在C语言中非常重要,对于程序的正确性和性能都有着重要的影响。

字节对齐的原理是为了优化内存访问速度和空间利用率,避免因为不对齐而导致的性能降低。

在C语言中,变量的存储空间是以字节为单位进行分配的,而不同的数据类型在内存中所占的字节数是不同的。

字节对齐的目的是为了确保不同类型的变量在内存中的起始地址是对齐的,这样可以提高访问效率。

C语言中的字节对齐规则是由编译器来决定的,不同的编译器可能有不同的对齐规则。

一般来说,编译器会按照变量的自然对齐大小进行对齐。

自然对齐是指变量所占的字节数,例如char类型的变量自然对齐为1字节,int类型的变量自然对齐为4字节。

在进行字节对齐时,编译器会在变量之间插入一些空白字节,使得变量的起始地址能够满足对齐要求。

这样一来,虽然会浪费一些空间,但可以提高内存的访问效率。

例如,如果int类型的变量要求按4字节对齐,而其起始地址为0x1000,那么在其后紧接着的变量的起始地址就必须是0x1004,即起始地址必须是4的倍数。

字节对齐的规则并不是固定的,它受到编译器的影响。

有些编译器的默认对齐规则可能是按照变量的自然对齐大小来对齐的,而有些编译器可能会有一些特殊的对齐规则。

此外,开发人员也可以通过编译器提供的指令来手动控制字节对齐的方式。

字节对齐的原理和规则虽然复杂,但它对于程序的正确性和性能优化至关重要。

如果变量没有按照正确的对齐方式进行存储,可能会导致内存访问错误,甚至引发程序崩溃。

而且,字节对齐也会影响程序的性能,如果变量没有按照对齐要求进行存储,可能会导致内存访问速度变慢,从而影响程序的执行效率。

为了正确地使用字节对齐,开发人员需要了解编译器的对齐规则,并且在编写代码时遵循这些规则。

在一些特殊情况下,开发人员也可以使用编译器提供的指令来手动控制字节对齐的方式,以满足特定的需求。

c语言结构体中的数组字节对齐

c语言结构体中的数组字节对齐

C语言结构体中的数组字节对齐在C语言中,结构体是一种用户自定义的数据类型,用于将不同类型的数据组合在一起。

结构体中常常包含多个成员变量,其中可能有数组类型的成员变量。

在结构体中使用数组时,需要了解数组字节对齐的概念和规则,以确保内存的最佳利用和访问的效率。

什么是字节对齐字节对齐是指在将数据存储在计算机内存中时,按照特定规则进行调整,以确保数据的存储和访问的效率。

字节对齐的规则可以对齐数据的起始地址或者数据的长度。

计算机中的数据存储是按照字节(Byte)来划分的,一个字节通常由8个二进制位组成。

字节对齐的主要目的是为了节省内存和提高访问效率。

在C语言中,结构体中的成员变量通常按照字节对齐的规则来排列。

C语言结构体中的数组字节对齐规则在C语言中,结构体中的数组字节对齐规则通常遵循以下原则:1.结构体的起始地址必须是所有成员变量所要求对齐方式的最小公倍数。

2.结构体中的每个成员变量的地址必须是它本身的大小的整数倍。

3.结构体的总大小必须是其最大成员变量大小的整数倍。

根据字节对齐规则,如果结构体中的成员变量的累计大小不是字节对齐的倍数,编译器会在成员变量之间添加填充字节,以满足对齐要求。

这些填充字节在结构体的占用空间中不可访问。

填充字节的目的是将后续成员变量的地址对齐,以提高内存访问效率。

数组字节对齐的示例为了更好地理解数组字节对齐的规则,我们来看一个示例。

#include <stdio.h>struct MyStruct {char c;int i;char arr[3];};int main() {struct MyStruct s;printf("sizeof(MyStruct) = %lu\n", sizeof(struct MyStruct));printf("sizeof(s.c) = %lu\n", sizeof(s.c));printf("sizeof(s.i) = %lu\n", sizeof(s.i));printf("sizeof(s.arr) = %lu\n", sizeof(s.arr));return 0;}输出结果:sizeof(MyStruct) = 12sizeof(s.c) = 1sizeof(s.i) = 4sizeof(s.arr) = 3在这个示例中,我们定义了一个包含一个字符类型变量、一个整型变量和一个长度为3的字符数组的结构体MyStruct。

C语言字节对齐

C语言字节对齐

C语言字节对齐字节对齐的由来程序在运行时会将数据临时存放在内存中,芯片内核需要对这些数据进行计算,不断的读取内存以获得数据,并将计算结果写入内存。

计算机体系经过若干年的发展,最终确定了以8bits作为其基本的存储单元——byte(字节),这是每个地址所对应的最小访问单元,在C语言中对应一个char型的变量。

下图为芯片内核访问内存的示意图。

芯片内核通过控制总线控制内存的动作,通过地址总线告知内存地址,数据总线上出现交互的数据。

图1访问内存示意图假设上图是8位机的示意图,那么数据总线的宽度是8bits,由8根数据线组成,这样芯片内核与内存之间一次就可以同时交换8个bits的数据,正好是一个字节。

图中右侧的每个小格子代表一个存储地址,对应一个字节。

下面通过一段C语言代码来具体看看芯片内核与内存之间的数据交互过程。

char data[2];data[0]=2;data[1]=data[0]+1;第一行代码定义了2个字节的数组data。

假设data数组被编译到地址0x100,那么data[0]这个字节就被存储在地址为0x100的内存空间,data[1]这个字节就被存储在地址为0x101的内存空间。

第二行对应的硬件动作是将数据2存入到data[0]中,也就是将数据2存入到内存中的0x100地址,执行这条语句时,芯片内核对控制总线、地址总线和数据总线进行操作,控制总线上出现写信号,地址总线上出现数据0x100,数据总线上出现数据0x02。

此时内存就知道需要将数据2写入到地址0x100中,完成一次写操作。

第三行先读出data[0]中的数据,芯片内核将控制总线置为读信号,将地址总线置为0x100,此时,内存就会从其内部取出0x100地址中的数据,也就是数据2,2将出现在数据总线上,此时芯片内核就会通过数据总线读取到data[0]中的数据了。

接下来芯片内核计算2+1=3,需要将数字3写入到data[1]中,芯片内核将控制总线置为写信号,将地址总线置为0x101,将数据总线置为3,内存接收到这些信号后,就会将数据3存入到其内部0x101地址中,完成本次操作。

C语言的位域,字节对齐

C语言的位域,字节对齐

C的位域(bit fields )struct bs{int a:7;int b:2;int c:1;};表示用一个整数的前8位表示a,用一个整数的2位表示b,用一个整数的1位的来表示c,位域定义不能超过数据定义类型的最大位,如struct {char a:9; //char 最大值为8位int b:33; //int 的最大值为32,不能超过其中定义值}位域有如下特殊定义,1)只要不超过数据定义最大值,多个位域可以定义一个数据单位里,如下是合法,定义,也是常用定义Struct PC_PIN{Char bit0:1,bit1:1,Bit2:1,Bit3:1,Bit4:1,Bit5:1,Bit6:1,Bit7:1;}2)位域可以采用’匿名',定义,这样程度就不能使用这些位,这样定义纯粹是起占位用.struct foo1 {int a : 1;int : 2;short c : 1;};上例中,在a和c中有一个2位的匿名占位struct bs{unsigned a:4unsigned :0 /*空域*/unsigned b:4 /*从下一单元开始存放*/unsigned c:4}在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。

位域占位计算有点复杂1.定义位域不足一个数据位的,按一个完整数据算Struct tagA{Int a:3;Int b;};Sizeof()值是8,因为a仍然按4位来核算.2.如果连续定义几点相同类型.而位域总合不超过类型总位数长度的,会被编译器设为一个合并为一个位域定义如struct tagA{int a:1;int b:2;int c;3}等同于struct tagB{Int a:1,b:2,c:3;};Sizeof()的长度都是4,因为tagA的各个成员加起长度都没有超过32,所以仍然为43.aaa位域的被广泛应用于8位单片机编程中.因为一个8位寄存器刚好是一个char 的宽度,因为可以定义一个8个位位域来对寄存器的各个位进行存取.这样程序比较简单并且好理解.但在32位CPU应用反而不广泛,因为32CPU的寄存器是为32位宽度,正好是一个int 的宽度,但int 在不同CPU中的表示顺序位是不一致的.在不同字节序CPU里定义的位域,有一些不样,换句话说,定义这样位域需要定义两套类型.如ip的头定义.struct iphdr {#if defined(__LITTLE_ENDIAN_BITFIELD)__u8 ihl:4,version:4;#elif defined (__BIG_ENDIAN_BITFIELD)__u8 version:4,ihl:4;#else#error "Please fix <asm/byteorder.h>"#endif__u8 tos;__u16 tot_len;__u16 id;__u16 frag_off;__u8 ttl;__u8 protocol;__u16 check;__u32 saddr;__u32 daddr;/*The options start here. */};使用反而不如位操作定义方便,因此32位CPU使用位域有一些麻烦字节对齐现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但为为了CPU访问数据的快速,通常都要求数据存放的地址是有一定规律的.比如在32位CPU上,一般要求变量地址都是基于4位,这样可以保证CPU用一次的读写周期就可以读取变量.不按4位对齐,如果变量刚好跨4位的吗,这样需要CPU两个读写周期.效率自然低下.因此,在现代的编译器都会自动把复合数据定义按4位对齐,以保证CPU 以最快速度读取,如下例(gcc version 编译器(32位x86平台))struct A {int a;char b;short c;};结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short 型数据一个。

结构体字节对齐的方法

结构体字节对齐的方法

结构体字节对齐的方法全文共四篇示例,供读者参考第一篇示例:结构体字节对齐是编程中一个非常重要的概念,尤其在涉及到内存对齐的底层编程中更是不可或缺。

在结构体的定义中,每个元素都需要在内存中占用一定的空间,而结构体整体的大小受到字节对齐规则的限制。

本文将介绍结构体字节对齐的方法及其原理,希望能帮助读者更好地理解和掌握这一概念。

一、什么是字节对齐字节对齐是指在结构体中每个元素按照特定的规则分配内存空间,以便提高内存读取的效率。

在计算机系统中,一般要求数据在内存中的存储地址是某个特定值的倍数,这个特定值就是对齐系数。

常用的对齐系数有1、2、4、8等,根据不同的系统和编译器,对齐系数可能会有所不同。

二、结构体字节对齐的原理在C语言中,结构体的内存对齐是通过编译器来进行处理的。

当定义一个结构体时,编译器会按照一定的规则对结构体中的元素进行字节对齐,以便提高读取效率。

具体的对齐规则如下:1. 结构体中每个元素的偏移量必须是它自身类型大小的整数倍。

2. 结构体的大小必须是最大元素类型大小的整数倍。

3. 结构体的对齐系数为结构体中所有元素类型大小的最大值。

通过这些规则,编译器可以在编译时确定结构体的大小,并根据对齐系数进行内存对齐,从而提高内存访问的效率。

1. 使用#pragma pack指令在C语言中,可以使用#pragma pack指令来改变编译器默认的对齐系数。

通过指定pack(n)来设置n值,表示结构体的对齐系数为n。

这样可以在需要的时候自定义结构体的对齐系数,提高程序的效率。

```c#pragma pack(1)struct Student {char name[10];int age;float score;};```上面的代码中,通过#pragma pack(1)改变了结构体的对齐系数为1,从而可以确保结构体中的每个元素都按照一个字节进行对齐。

2. 使用__attribute__((packed))关键字在GCC编译器中,可以使用__attribute__((packed))关键字来实现对齐系数的设置。

c++字节对齐规则

c++字节对齐规则

c++字节对齐规则C++字节对齐规则是指在内存中创建数据结构时,变量的地址必须是某个特定值的倍数。

这个特定值称为对齐系数,通常是1、2、4、8等。

遵循字节对齐规则可以提高程序的性能和效率。

本文将介绍C++字节对齐规则的基本原理、对齐方式以及对齐的应用场景。

在C++中,字节对齐是为了优化内存访问的效率。

当变量被创建在内存中时,根据对齐系数,编译器会将变量的地址对齐到某个特定的地址。

这样一来,CPU在访问这些内存地址时可以更快地读取数据,提高了程序的运行效率。

C++中的对齐方式有两种,分别是数据成员对齐和结构体对齐。

在数据成员对齐中,每个数据成员的地址都必须是它自身长度和对齐系数中较大值的倍数。

结构体对齐则是指结构体的起始地址必须是结构体成员中最大对齐系数的倍数。

对齐方式的选择可以通过编译器的设置来进行调整。

一般来说,编译器会提供默认的对齐方式,但也可以通过一些特殊的指令或者预处理宏来设置自定义的对齐方式。

对于大多数应用场景来说,采用默认的对齐方式就可以满足需求。

字节对齐规则在实际开发中有很多应用场景。

首先,结构体对齐可以提高结构体对象数组的访问速度。

当一个结构体对象数组被创建在内存中时,根据结构体成员中最大的对齐系数,编译器会将每个结构体对象的起始地址对齐到这个系数的倍数上。

这样一来,在访问结构体数组时,CPU可以更快地进行内存读取,提高了程序的性能。

其次,字节对齐规则在跨平台开发中也非常重要。

由于不同平台上的CPU和操作系统对字节对齐的要求可能不同,因此在进行跨平台开发时,需要确保代码在不同平台上运行时,字节对齐的规则是一致的。

这可以通过使用特定的编译指令或者预处理宏来实现。

此外,字节对齐规则在处理网络协议、文件格式等底层数据结构时也非常常见。

在这些场景中,确保数据在内存中的排列方式与协议或者文件格式的要求一致非常重要。

如果不遵循字节对齐规则,可能会导致数据解析错误或者性能下降。

总结起来,C++字节对齐规则是为了提高程序性能和效率而设计的。

C语言字节对齐__align()讲解

C语言字节对齐__align()讲解
五、什么时候需要设置对齐
在设计不同 CPU 下的通信协议时,或者编写硬件驱动程序时寄存器的结构这两个地 方都需要按一字节对齐。即使看起来本来就自然对齐的也要使其对齐,以免不同的编译器生 成的代码不一样.
一、快速理解 1. 什么是字节对齐? 在 C 语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如 int、long、 float 等)的变量,也可以是一些复合数据类型(如数组、结构、联合等)的数据单元。在 结构中,编译器为结构的每个成员按其自然边界(alignment)分配空间。各个成员按照它 们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。 为了使 CPU 能够对变量进行快速的访问,变量的起始地址应该具有某些特性,即所谓的”对 齐”. 比如4字节的 int 型,其起始地址应该位于4字节的边界上,即起始地址能够被4整除. 2. 字节对齐有什么作用? 字节对齐的作用不仅是便于 cpu 快速访问,同时合理的利用字节对齐可以有效地节省存储空 间。 对于32位机来说,4字节对齐能够使 cpu 访问速度提高,比如说一个 long 类型的变量,如果 跨越了4字节边界存储,那么 cpu 要读取两次,这样效率就低了。但是在32位机中使用1字节 或者2字节对齐,反而会使变量访问速度降低。所以这要考虑处理器类型,另外还得考虑编 译器的类型。在 vc 中默认是4字节对齐的,GNU gcc 也是默认4字节对齐。 3. 更改 C 编译器的缺省字节对齐方式 在缺省情况下,C 编译器为每一个变量或是数据单元按其自然对界条件分配空间。一般地, 可以通过下面的方法来改变缺省的对界条件: · 使用伪指令#pragma pack (n),C 编译器将按照 n 个字节对齐。 · 使用伪指令#pragma pack (),取消自定义字节对齐方式。 另外,还有如下的一种方式: · __attribute((aligned (n))),让所作用的结构成员对齐在 n 字节自然边界上。如果结 构中有成员的长度大于 n,则按照最大成员的长度来对齐。 · __attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数 进行对齐。 4. 举例说明 例1 struct test { char x1; short x2; float x3; char x4; }; 由于编译器默认情况下会对这个 struct 作自然边界(有人说“自然对界”我觉得边界更顺 口)对齐,结构的第一个成员 x1,其偏移地址为0,占据了第1个字节。第二个成员 x2为 short 类型,其起始地址必须2字节对界,因此,编译器在 x2和 x1之间填充了一个空字节。结构的 第三个成员 x3和第四个成员 x4恰好落在其自然边界地址上,在它们前面不需要额外的填充 字节。在 test 结构中,成员 x3要求4字节对界,是该结构所有成员中要求的最大边界单元, 因而 test 结构的自然对界条件为4字节,编译器在成员 x4后面填充了3个空字节。整个结构 所占据空间为12字节。 例2 #pragma pack(1) //让编译器对这个结构作1字节对齐

c语言4字节对齐指令

c语言4字节对齐指令

C语言4字节对齐指令一、什么是对齐指令1.1 对齐的概念在计算机中,对齐是指数据在内存中存储的方式。

内存中的数据是以字节为单位进行存储的,而对齐就是数据在内存中存储时的起始位置需要与其自身的大小对齐。

1.2 对齐的优势对齐的目的是为了提高计算机的访问速度。

当数据对齐之后,CPU的访问操作会更加高效,从而提高程序的执行效率。

二、数据对齐的原则数据的对齐有一定的规则,其中最常见的是按照字节对齐的原则进行排列。

2.1 字节对齐原则在C语言中,数据的字节对齐原则是根据数据类型的大小来确定的。

一般来说,对于基本数据类型,其对齐规则如下所示:•char类型不需要对齐,可以从任意位置开始存储。

•short类型需要2字节对齐,即起始地址必须是2的倍数。

•int类型需要4字节对齐,即起始地址必须是4的倍数。

•long类型需要8字节对齐,即起始地址必须是8的倍数。

2.2 结构体对齐原则对于结构体中的成员变量,其对齐规则也是按照字节对齐的原则进行排列的。

结构体中的成员变量按照其自身的大小顺序存放,并且每个成员变量的起始地址需要满足对齐规则。

三、C语言的对齐指令C语言提供了一些对齐指令,可以用来控制数据的对齐方式。

对齐指令可以通过编译器的选项来设置,也可以使用特殊的关键字进行设置。

3.1 编译器选项设置对齐方式编译器提供了一些选项来设置数据的对齐方式,其中最常用的是-malign-double 选项。

该选项可以控制double类型的对齐方式,一般情况下,我们可以将其设置为-malign-double=8,表示使用8字节对齐方式。

3.2 结构体的对齐指令在C语言中,可以使用#pragma pack(n)指令来设置结构体的对齐方式。

其中n表示对齐的字节数,常用的值为1、2、4、8等。

3.3 成员变量的对齐指令对于结构体中的某个成员变量,可以使用__attribute__((aligned(n)))指令来单独设置其对齐方式,其中n表示对齐的字节数。

字节对齐(强制对齐以及自然对齐)

字节对齐(强制对齐以及自然对齐)

字节对齐(强制对齐以及⾃然对齐)struct {}node;32为的x86,window下VC下sizeof(node)的值为1,⽽linux的gcc下值为0;⼀、WINDOWS下(VC--其实GCC和其原理基本⼀样,象这种问题,⼀般要查具体的编译器设置)字节对齐的规则:1、⼀般设置的对齐⽅式为1,2,4字节对齐⽅式,VC⼀般默认为4字节(最⼤为8字节)。

结构的⾸地址必须是结构内最宽类型的整数倍地址;另外,结构体的每⼀个成员起始地址必须是⾃⾝类型⼤⼩的整数倍(需要特别注意的是windows下是这样的,但在linux的gcc编译器下最⾼为4字节对齐),否则在前⼀类型后补0;这⾥特别提到的是数组⼀定要注意,⽽且在⼀些编程的技巧中,我们可以使⽤数组强制字节达到对齐的⽬的。

这在⽹络编程中是很常见的。

举例:⽐如CHAR型占⽤空间为1字节,则其起始位置必须可被1整除。

INT为4字节,其起始位置必须被4带队,依次类推。

(我们假定类或结构体的起始位置为0位置,其实编译器是在开辟空间时,会寻找起始位置可被结构内最宽类型整除的地址做为开始地址,因此我们可以假定其为0值,因为这0值可以被任意的类型整除。

)2、结构体的整体⼤⼩必须可被对齐值整除,默认4(默认,且结构中的类型⼤⼩都⼩于默认的4)。

3、结构体的整体⼤⼩必须可被本结构内的最宽类型整除。

(其实和上⼀条是⼀样的,但这⾥独⽴出来,起注意作⽤。

⽐如结构体⾥的有DOUBLE,那么结构的⼤⼩最后必须可被8整除)注意:GCC不是这样,就是最⾼只能被4整除,它是个死的。

否则(2、3条),编译器会在结构的最后添充⼀定的特定字符来补齐。

struct T{char ch;double d ;};在VC中是16个字节,GCC中为12个字节。

4、对于结构体内嵌套结构体的形势,规定是必须按照基本数据类型来定义,⽽不能以嵌套结构⼤⼩来做为上三种使⽤的基准。

⼆、举例:struct A{int a;char b;short c;};struct B{char b;int a;short c;};struct C{double t;char b;int a;short c;};struct D{char b;double t;int a;short c;};在VC中,SIZEOF这四个结构体,分别为:8、12、24、24;我们先谈第⼀个,(说明⼀下,在考虑结构体⼤⼩时,我们基本可以忽略起始地址的问题,因为这个编译器会⾃动为我们做好,见上⾯的说明),结构体内⾸先是⼀个INT的4字节,起始地址假定为0,整除4,其⼩于等于默认的4字节对齐且0为4(INT的占⽤空间)的整数倍,所以,其占四个字节;其后为起始地址为5,空间为1个字节的CHAR,⼩于4且5为1(CHAR占⽤空间)的整数倍,故占⽤1个字节,然后是⼀个起始地址为5占2个字节的SHORT,其⼩于4,但5不为2的整数倍,故补齐⼀个字节,从第6个字节开始,占2字节空间。

gcc结构体字节对齐编译参数

gcc结构体字节对齐编译参数

gcc结构体字节对齐编译参数gcc编译器是一款常用的C语言编译器,它可以将我们编写的C代码转换成可执行的机器码。

在使用gcc编译器时,我们可以通过一些特定的编译参数来控制编译过程中的一些细节,比如结构体的字节对齐。

字节对齐是指在结构体中,数据成员按照一定的规则进行排列,以便于CPU访问和读取。

由于CPU对齐访问数据的效率更高,因此在结构体中进行字节对齐可以提高程序的执行效率。

在gcc中,我们可以使用"-malign-structs"参数来控制结构体的字节对齐方式。

这个参数可以接受一个整数参数,表示对齐的字节数。

例如,"-malign-structs=4"表示按照4字节对齐。

字节对齐的方式有两种,分别是按照成员的自然对齐和按照最大对齐方式。

自然对齐是指按照成员本身的大小进行对齐,比如一个int 类型的成员会按照4字节对齐。

最大对齐方式是指按照结构体中最大成员的大小进行对齐,比如一个结构体中包含一个int类型和一个char类型的成员,那么整个结构体的对齐方式将按照4字节对齐。

为了能够更好地理解字节对齐的影响,我们可以通过一个具体的例子来说明。

假设我们有一个结构体如下所示:```cstruct Example {int a;char b;double c;};```如果我们不使用字节对齐的方式进行编译,那么结构体的字节排列方式可能如下所示:```| a (4字节) | b (1字节) | c (8字节) |```可以看到,结构体的内存布局并不是按照成员的自然对齐方式进行排列的。

这样一来,当我们访问结构体中的成员时,CPU可能需要进行额外的处理,从而降低程序的执行效率。

而如果我们使用字节对齐的方式进行编译,比如使用"-malign-structs=4"参数,那么结构体的字节排列方式可能如下所示:```| a (4字节) | 空闲字节 (3字节) | b (1字节) | 空闲字节 (7字节) | c (8字节) |```可以看到,结构体的内存布局按照最大对齐方式进行排列,每个成员都被对齐到4字节的边界上。

字节对齐作用

字节对齐作用

字节对齐作用字节对齐作用什么是字节对齐字节对齐是一种数据存储方式,用于提高计算机内存的读取效率。

在计算机中,数据被存储为字节的形式,每个字节有固定的大小。

字节对齐的原理计算机在读取数据时,通常以字节为单位进行操作。

为了提高读取效率,计算机会将数据按照一定规则进行对齐。

字节对齐的原理是按照数据类型的大小,将数据存储在内存中的地址按照一定规则进行调整,使得数据可以更快地被读取和处理。

字节对齐的作用字节对齐在计算机中具有重要的作用,主要体现在以下几个方面:•提高读取效率:字节对齐可以减少对内存的读取次数,提高读取效率。

当数据按照自然边界对齐时,可以通过一次读取多个字节,减少读取的次数,提高数据读取的效率。

•节省存储空间:字节对齐可以减少内存空间的浪费。

当数据按照对齐规则进行对齐时,可以利用内存中的空闲字节,避免空间的浪费,节省存储空间。

•确保数据的连续存储:字节对齐可以保证数据在内存中的连续存储,减少内存碎片的产生。

当数据按照对齐规则进行对齐时,可以确保数据之间没有空隙,避免内存碎片的产生,提高内存的利用率。

•增加数据的可移植性:字节对齐可以增加数据的可移植性。

不同的计算机体系结构对字节对齐的要求可能不同,通过字节对齐可以保证数据在不同的计算机上都可以正确地读取和处理。

字节对齐的规则字节对齐的规则取决于具体的编程语言和计算机体系结构。

在C语言中,常用的字节对齐规则是按照数据类型的大小进行对齐,即数据类型的长度必须是其对齐要求的整数倍。

具体的对齐规则可以通过编译器的选项或者编程语言的特定语法进行设置和控制。

以下是常见的对齐规则:•对齐到自然边界:数据类型按照自身的大小进行对齐。

例如,一个int类型的数据通常按照4字节对齐。

•对齐到指定边界:数据类型按照指定的边界进行对齐。

例如,一个结构体可以通过设置#pragma pack(n)指令,将其对齐到n字节的边界。

•默认对齐规则:编译器根据具体的体系结构和编译选项进行对齐。

c语言字节对齐规则

c语言字节对齐规则

c语言字节对齐规则
C语言字节对齐规则是程序员在进行内存分配和结构体定义时需要遵守的一些规则。

这些规则是由编译器制定的,用于保证内存对齐,提高程序的执行效率。

下面列举一些常见的C语言字节对齐规则:
1. 对齐原则:结构体变量的起始地址必须是其最宽基本类型成员大小的倍数,也就是说,结构体变量的大小必须是其成员大小的倍数。

2. 数据成员对齐规则:结构体中的每个成员都按照其自身的大小进行对齐,例如char类型的成员对齐于1字节边界,int类型的成员对齐于4字节边界。

3. 结构体对齐规则:结构体中的成员按照其定义顺序进行排列,如果前面的成员已经对齐,但是后面的成员因为大小不同而无法对齐时,编译器会在前面的成员后面插入一些填充字节,以保证后面的成员能够对齐。

4. 结构体嵌套对齐规则:结构体中嵌套的结构体也需要进行对齐,对齐原则同上。

5. 指针对齐规则:指针的大小为4字节或8字节,根据机器的位数而定。

指针变量的对齐方式与其所指向的数据类型相同。

6. 最大对齐原则:结构体的最大对齐值为其成员中的最大对齐值,也就是说,结构体的对齐值不能超过其成员中的最大对齐值。

以上就是C语言字节对齐规则的一些常见内容。

理解和遵守这些规则可以提高程序的执行效率,减少内存的浪费,从而使程序更加高效。

c对齐

c对齐

C语言对齐一、为什么要对齐不同的处理器访问内存的方法不同,一般来讲都支持单字节访问。

为了提高效率16位机可能还支持按2字节访问,32位机可能还支持按4字节访问。

按多字节访问一般需要地址对齐。

比如按2字节访问时,要求地址的最低位为0,即按2字节对齐。

按4字节访问时,要求地址的最低2位为0,即按4字节对齐。

如果地址是符合对齐要求的,就可以实现多字节一次访问,提高访问效率。

否则的话则须拆成单个字节逐个访问。

二、C语言的对齐C语言是跨平台的编程语言,他默认的对齐方式是按照变量的长度进行对齐。

比如char 为一个字节对齐,short为2个字节对齐,long为4个字节对齐。

为了提高内存的利用率,对于全局变量,编译器会把所有同长度的变量组合在一起分配空间,空间的首地址符合对齐关系。

比如给所有非零初值的单字节变量分配一块空间。

例1:char a = 1; short b = 0; char c = 0; char d = 3; short e;那么“a”和“d”会被分配在同一块空间,空间首地址为1字节对齐,“b”和“e”会被分配在同一块空间,空间首地址为2字节对齐。

(无初值一般等同于初值为零)三、结构体的对齐结构体里面的变量默认是单独符合对齐规律的(因为结构体的变量必须连续分配,不能够拆分开统一分配)。

通过#pragmapack(x)可以改变默认的对齐规律,把大于“x”字节对齐的变量压缩到“x”字节对齐,小于“x”字节对齐的变量不受影响。

例2:typedef struct{u8 a;u16 b;u32 c;}test1;test1的内存分配如下表:a填充b b c c c ctypedef struct{u32 c;u16 b;u8 a;}test2;test2的内存分配如下表:c c c c b b a填充#pragma pack(1) //对于16位和32位,使用1字节压缩对齐会严重影响效率,慎用!typedef struct{u8 a;u16 b;u32 c;}test3;#pragma pack() //恢复默认压缩字节数test3的内存分配如下表:a b b c c c c四、结构体的尾部填充一些编译器(如KEIL)会在结构体的尾部填充,使结构体的大小为其内部最大对齐数的整数倍。

c语言中的结构体和字节对齐

c语言中的结构体和字节对齐

c语言中的结构体和字节对齐结构体结构体的概念★计算机程序设计语言都有数据类型的概念★数据类型一般有基本类型和用户自定义类型★在c语言中,基本类型有int型、double型、char型等等。

★而结构体类型则属于用户自定义类型,是由基本类型组合而成的复杂类型。

★定义好的结构体类型可以像基本类型一样去定义此类型的变量。

定义结构体类型和定义结构体类型变量★我们先看看定义结构体类型的一般形式:struct 结构体标示符{结构体元素;};如下:struct StructDemo{char c;int i;};★定义结构体类型变量方式一:定义类型的同时定义变量,如下:struct StructDemo{char c;int i;}sd1,sd2;这样就定了两个结构体变量sd1,sd2了,这两个变量的类型是struct StructDemo类型。

★定义结构体类型变量方式二:定义类型之后定义变量,如下:struct StructDemo{char c;int i;};这个定义说明我们已经定义完成了一个新的类型,这个类型说明符就是structStructDemo。

所以我们可以用此来定义变量了。

如下:struct StructDemo sd1,sd2;★定义结构体类型变量方式三:类型说明符重命名的方法。

学习C语言的朋友,对typedef估计不会陌生的,用它可以给类型说明符一个别名,此名字和原来的名字具有同样意义。

如:typedef int zhengxing;那么int i和zhengxing i是一样的意思。

同样的道理也可运用于我们自定义的数据类型。

typedef struct StructDemo SD;SD sd1,sd2;结构体类型的初始化★定义的同时初始化,如:struct StructDemo sd1 = {‘A’,10},sd2 = {‘B’,12};SD sd1 = {‘A’,10},sd2 = {‘B’,12};struct StructDemo{char c;int i;} sd1 = {‘A’,10},sd2 = {‘B’,12};★定义之后再初始化,如:sd1 = {‘A’,10};sd2 = {‘B’,12};sd1.c = ‘D’;sd1.i = 20;结构体运用举例1我们将上面所说的结构体的定义、定义结构体类型变量、初始化用一个实际的程序来呈现,我现在这台机器上装的linux系统是OpenSuSe,所以我们打开OpenSuSe,打开终端,利用vim编辑程序StructDemo01.c如下:编译运行如下:结构体的大小问题计算机程序语言中的数据类型在使用时在计算机中都会占有一定的内存空间,结构体类型是用户自定义类型,也属于数据类型的一种,那么它在计算机内存中占有的空间大小又是什么情况呢?下面我们来看一下。

c语言 字节对齐问题造成复位

c语言 字节对齐问题造成复位

c语言字节对齐问题造成复位在C语言中,字节对齐是一个与硬件体系结构和编译器实现相关的概念。

字节对齐是指结构体中成员变量的存储地址相对于结构体的起始地址的偏移量必须是成员变量大小的整数倍。

字节对齐的问题可能导致结构体的大小变得比成员变量的总大小更大,这可能会对内存布局和访问产生影响,特别是在涉及到硬件寄存器、外设寄存器、或者与硬件通信的情况下。

考虑以下示例:#include <stdio.h>struct Example {char a; // 1字节int b; // 4字节char c; // 1字节};int main() {printf("Size of struct: %lu bytes\n", sizeof(struct Example));return 0;在这个例子中,由于字节对齐的原因,struct Example 的大小可能会大于 1 + 4 + 1 = 6 字节。

实际上,由于对齐,struct Example 的大小可能是8字节,这取决于编译器和编译器的配置。

为了解决这个问题,你可以使用编译器特定的指令来指定对齐方式。

在一些编译器中,可以使用 #pragma pack 指令。

例如,在GCC 中,可以这样使用:#pragma pack(push, 1)struct Example {char a; // 1字节int b; // 4字节char c; // 1字节};#pragma pack(pop)这个指令告诉编译器按照1字节的对齐方式来布局结构体。

但需要注意的是,这可能会导致性能下降,因为对齐的结构体在某些架构上的访问速度可能会变慢。

在解决字节对齐问题时,最好的做法是了解并理解你的编译器和目标体系结构的默认对齐方式,并根据实际需求进行适当的优化。

c语言字节对齐规则

c语言字节对齐规则

c语言字节对齐规则
C语言字节对齐规则
字节对齐(Byte Alignment)是指内存地址和数据类型中字节的排列位置,由于内存地址以字节为单位进行分配,数据类型却有特定的字节内存空间,所以为了让数据类型跟内存地址对齐,就必须让数据类型的内存空间按照一定的对齐规则进行排列,这样才能让数据类型最小的内存空间能得到最优的分配。

C语言的字节对齐规则
1、C语言中,结构体的属性是以字节为单位进行分配的。

2、对于大小为1字节的变量,不管在结构体的哪个位置,都不会进行字节对齐,一个变量一个字节就是一个字节,不会增加其他字节的占用。

3、对于大小为2字节的变量,要求其在结构体的位置为偶数,将会对其右边多出一个字节的占用,但是不会多出一个字节的内存,只是在内存的右边多出一个字节的位置而已。

4、对于大小为4字节的变量,要求其在结构体的位置为4的倍数,也会对其右边多出三个字节的占用,但是不会多出三个字节的内存,只是在内存的右边多出三个字节的位置而已。

5、对于大小为8字节的变量,要求其在结构体的位置为8的倍数,也会对其右边多出七个字节的占用,但是不会多出七个字节的内存,只是在内存的右边多出七个字节的位置而已。

6、C中的枚举常量和指针类型都会进行字节对齐,枚举常量和
指针类型都会被当做int类型来对齐,即按照4个字节的方式对齐。

7、C语言中,数组也会进行字节对齐,但是这里需要根据该数组的元素的大小来决定字节对齐的规则,如果数组的元素大小是1字节,则不进行字节对齐;如果是2字节,则按照2字节对齐规则进行字节对齐;如果数组的元素大小是4字节,则按照4字节的对齐规则进行字节对齐;如果大于4字节,则按照8字节的对齐规则进行字节对齐。

C语言的字节对齐及#pragmapack的使用

C语言的字节对齐及#pragmapack的使用

C语言的字节对齐及#pragmapack的使用C编译器的缺省字节对齐方式(自然对界)在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。

在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间。

各个成员按照它们被声明的顺序在内存中顺序存储(成员之间可能有插入的空字节),第一个成员的地址和整个结构的地址相同。

C编译器缺省的结构成员自然对界条件为“N字节对齐”,N即该成员数据类型的长度。

如int型成员的自然对界条件为4字节对齐,而double类型的结构成员的自然对界条件为8字节对齐。

若该成员的起始偏移不位于该成员的“默认自然对界条件”上,则在前一个节面后面添加适当个数的空字节。

C编译器缺省的结构整体的自然对界条件为:该结构所有成员中要求的最大自然对界条件。

若结构体各成员长度之和不为“结构整体自然对界条件的整数倍,则在最后一个成员后填充空字节。

例子1(分析结构各成员的默认字节对界条界条件和结构整体的默认字节对界条件):struct Test{char x1; // 成员x1为char型(其起始地址必须1字节对界),其偏移地址为0char x2; // 成员x2为char型(其起始地址必须1字节对界,其偏移地址为1float x3; // 成员x3为float型(其起始地址必须4字节对界),编译器在x2和x3之间填充了两个空字节,其偏移地址为4char x4; // 成员x4为char型(其起始地址必须1字节对界),其偏移地址为8};因为T est结构体中,最大的成员为flaot x3,因些此结构体的自然对界条件为4字节对齐。

则结构体长度就为12字节,内存布局为1100 1111 1000。

例子2:#include <stdio.h>//#pragma pack(2)typedef struct{int aa1; //4个字节对齐 1111char bb1;//1个字节对齐 1short cc1;//2个字节对齐 011char dd1; //1个字节对齐 1} testlength1;int length1 = sizeof(testlength1); //4个字节对齐,占用字节1111 1011 1000,length = 12typedef struct{char bb2;//1个字节对齐 1int aa2; //4个字节对齐 01111short cc2;//2个字节对齐 11char dd2; //1个字节对齐 1} testlength2;int length2 = sizeof(testlength2); //4个字节对齐,占用字节1011 1111 1000,length = 12typedef struct{char bb3; //1个字节对齐 1char dd3; //1个字节对齐 1int aa3; //4个字节对齐 001111short cc23//2个字节对齐 11} testlength3;int length3 = sizeof(testlength3); //4个字节对齐,占用字节1100 1111 1100,length = 12typedef struct{char bb4; //1个字节对齐 1char dd4; //1个字节对齐 1short cc4;//2个字节对齐 11int aa4; //4个字节对齐 1111} testlength4;int length4 = sizeof(testlength4); //4个字节对齐,占用字节1111 1111,length = 8int main(void){printf("length1 = %d.\n",length1);printf("length2 = %d.\n",length2);printf("length3 = %d.\n",length3);printf("length4 = %d.\n",length4);return0;}改变缺省的对界条件(指定对界)· 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。

c语言 结构体单字节对齐 声明

c语言 结构体单字节对齐 声明

一、C语言中结构体的定义与用途C语言是一种广泛应用于系统编程和嵌入式开发的程序设计语言,它具有高效、灵活等特点,其中结构体是C语言的一个重要特性。

结构体可以被看作是一种自定义的数据类型,它允许程序员将不同类型的数据组合在一起,形成一个新的数据类型,从而更好地组织和管理数据。

二、结构体的单字节对齐原理在C语言中,结构体的成员是按照其数据类型的大小顺序排列的,每个成员在结构体中的偏移量必须是它的对齐值的整数倍。

对齐值取决于数据类型,通常为该类型的字节数。

而结构体本身的大小则是按照其成员大小的总和来决定的。

在C语言中,为了提高程序的执行效率,结构体成员的位置区域需要按照一定的字节对齐规则进行排列,以便在内存中能够高效地访问结构体的成员。

三、结构体的单字节对齐声明方法在C语言中,为了满足特定的内存对齐需求,程序员可以使用特定的方法来声明结构体的对齐方式。

一般来说,可以通过编译器提供的一些指令或者预处理器宏来实现对齐设置。

1. 使用#pragma pack(N)指令在C语言中,可以使用#pragma pack(N)指令来指定结构体成员的对齐值。

其中N表示对齐值,它可以取1、2、4或8等值,具体取决于实际需求。

该指令将结构体成员的对齐值设置为N,从而可以实现单字节对齐。

2. 使用__attribute__((aligned(N)))属性在一些C语言编译器中,可以使用__attribute__((aligned(N)))属性来指定结构体的对齐方式。

其中N表示对齐值,与#pragma pack(N)的功能类似,也可以取1、2、4或8等值。

通过在结构体定义时加上该属性,可以实现单字节对齐。

3. 使用预处理器宏在C语言中,还可以通过定义一些预处理器宏来实现对齐设置。

可以定义一个宏来指定结构体成员的对齐值,然后在结构体定义时使用该宏来实现单字节对齐。

四、结构体单字节对齐的优缺点分析结构体单字节对齐可以确保结构体成员被紧凑地存储在内存中,从而减少内存的浪费。

字节对齐问题,gcc编译器,对齐字节修改

字节对齐问题,gcc编译器,对齐字节修改

字节对齐问题,gcc编译器,对齐字节修改嵌入式开发要编的第四个程序:字节对齐问题示例程序一:#includestruct st1{int x;short y;char z;};struct st2{short y;int x;char z;};int main(intargc, char * argv[]){printf("sizeof(struct st1) = %d\n", sizeof(struct st1)); printf("sizeof(struct st2) = %d\n", sizeof(struct st2)); return 0;} //默认的是4字节对齐//输出结果://sizeof(struct st1) = 8 //sizeof(struct st1) = 12程序解释什么是字节对齐?为了使CPU能够对变量进行快速的访问,变量的起始地址应该具有某些特性,即所谓的”对齐”. 比如在32位系统下的的int型变量占 4 个字节,在分配内存时其起始地址应该位于4字节的边界上,即起始地址能够被4整除。

示例程序二:#pragma pack(1)struct st1{int x;short y;char z;};struct st2 {short y; int x;char z;};#pragma pack()int main(intargc, char * argv[]){struct st1 s1;struct st2 s2;printf("sizeof(struct st1) = %d\n", sizeof(struct st1)); printf("sizeof(struct st2) = %d\n\n", sizeof(struct st2));printf("st1 s1 Addr 0x%x \n", &s1);printf("st1 s1.x Addr 0x%x x int\n", &s1.x);printf("st1 s1.y Addr 0x%x y short\n", &s1.y);printf("st1 s1.z Addr 0x%x z char\n\n", &s1.z);printf("st1 s2 Addr 0x%x \n", &s2);printf("st1 s2.y Addr 0x%x y short\n", &s2.y);printf("st1 s2.x Addr 0x%x x int \n", &s2.x);printf("st1 s2.z Addr 0x%x z char\n", &s2.z);return 0;} //pragma pack(1)设置1字节对齐//输出结果//sizeof(struct st1) = 7//sizeof(struct st2) = 7//st1 s1 Addr 0xbfbaa0dd//st1 s1.x Addr 0xbfbaa0dd x int //st1 s1.y Addr 0xbfbaa0e1 y short //st1 s1.z Addr 0xbfbaa0e3 z char//st1 s2 Addr 0xbfbaa0d6//st1 s2.y Addr 0xbfbaa0d6 y short //st1 s2.x Addr 0xbfbaa0d8 x int //st1 s2.z Addr 0xbfbaa0dc z char程序解释修改默认字节对齐但是如果采用使用1字节或者2 字节对齐,会降低变量访问速度降低。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一.什么是字节对齐,为什么要对齐?现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。

对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。

一些平台对某些特定类型的数据只能从某些特定地址开始存取。

比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。

比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit 数据。

显然在读取效率上下降很多。

二.字节对齐对程序的影响:先让我们看几个例子吧(32bit,x86环境,gcc编译器):设结构体如下定义:struct A{ int a; char b; short c;};struct B{ char b; int a; short c;};现在已知32位机器上各种数据类型的长度如下:char:1(有符号无符号同)short:2(有符号无符号同)int:4(有符号无符号同)long:4(有符号无符号同)float:4 double:8那么上面两个结构大小如何呢?结果是:sizeof(strcut A)值为8sizeof(struct B)的值却是12结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一个,B也一样;按理说A,B大小应该都是7字节。

之所以出现上面的结果是因为编译器要对数据成员在空间上进行对齐。

上面是按照编译器的默认设置进行对齐的结果,那么我们是不是可以改变编译器的这种默认对齐设置呢,当然可以.例如:#pragma pack (2) /*指定按2字节对齐*/struct C{ char b; int a; short c;};#pragma pack () /*取消指定对齐,恢复缺省对齐*/sizeof(struct C)值是8。

修改对齐值为1:#pragma pack (1) /*指定按1字节对齐*/struct D{ char b; int a; short c;};#pragma pack () /*取消指定对齐,恢复缺省对齐*/sizeof(struct D)值为7。

后面我们再讲解#pragma pack()的作用.三.编译器是按照什么样的原则进行对齐的?先让我们看四个重要的基本概念:1.数据类型自身的对齐值:对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。

2.结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。

3.指定对齐值:#pragma pack (value)时的指定对齐值value。

4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。

有了这些值,我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐方式。

有效对齐值N是最终用来决定数据存放地址方式的值,最重要。

有效对齐N,就是表示“对齐在N 上”,也就是说该数据的"存放起始地址%N=0".而数据结构中的数据变量都是按定义的先后顺序来排放的。

第一个数据变量的起始地址就是数据结构的起始地址。

结构体的成员变量要对齐排放,结构体本身也要根据自身的有效对齐值圆整(就是结构体成员变量占用总长度需要是对结构体有效对齐值的整数倍,结合下面例子理解)。

这样就不能理解上面的几个例子的值了。

例子分析:分析例子B:struct B{ char b; int a; short c;};假设B从地址空间0x0000开始排放。

该例子中没有定义指定对齐值,在笔者环境下,该值默认为4。

第一个成员变量b的自身对齐值是1,比指定或者默认指定对齐值4小,所以其有效对齐值为1,所以其存放地址0x0000符合0x0000%1=0.第二个成员变量a,其自身对齐值为4,所以有效对齐值也为4,所以只能存放在起始地址为0x0004到0x0007这四个连续的字节空间中,复核0x0004%4=0,且紧靠第一个变量。

第三个变量c,自身对齐值为2,所以有效对齐值也是2,可以存放在0x0008到0x0009这两个字节空间中,符合0x0008%2=0。

所以从0x0000到0x0009存放的都是B内容。

再看数据结构B的自身对齐值为其变量中最大对齐值(这里是b)所以就是4,所以结构体的有效对齐值也是4。

根据结构体圆整的要求,0x0009到0x0000=10字节,(10+2)%4=0。

所以0x0000A到0x000B也为结构体B所占用。

故B从0x0000到0x000B 共有12个字节,sizeof(struct B)=12;其实如果就这一个就来说它已将满足字节对齐了, 因为它的起始地址是0,因此肯定是对齐的,之所以在后面补充2个字节,是因为编译器为了实现结构数组的存取效率,试想如果我们定义了一个结构B的数组,那么第一个结构起始地址是0没有问题,但是第二个结构呢?按照数组的定义,数组中所有元素都是紧挨着的,如果我们不把结构的大小补充为4的整数倍,那么下一个结构的起始地址将是0x0000A,这显然不能满足结构的地址对齐了,因此我们要把结构补充成有效对齐大小的整数倍.其实诸如:对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double 类型,其自身对齐值为4,这些已有类型的自身对齐值也是基于数组考虑的,只是因为这些类型的长度已知了,所以他们的自身对齐值也就已知了.同理,分析上面例子C:#pragma pack (2) /*指定按2字节对齐*/struct C{ char b; int a; short c;};#pragma pack () /*取消指定对齐,恢复缺省对齐*/第一个变量b的自身对齐值为1,指定对齐值为2,所以,其有效对齐值为1,假设C从0x0000开始,那么b存放在0x0000,符合0x0000%1= 0;第二个变量,自身对齐值为4,指定对齐值为2,所以有效对齐值为2,所以顺序存放在0x0002、0x0003、0x0004、0x0005四个连续字节中,符合0x0002%2=0。

第三个变量c的自身对齐值为2,所以有效对齐值为2,顺序存放在0x0006、0x0007中,符合0x0006%2=0。

所以从0x0000到0x00007共八字节存放的是C 的变量。

又C的自身对齐值为4,所以C的有效对齐值为2。

又8%2=0,C 只占用0x0000到0x0007的八个字节。

所以sizeof(struct C)=8.四.如何修改编译器的默认对齐值?1.在VC IDE中,可以这样修改:[Project]|[Settings],c/c++选项卡Category的Code Generation 选项的Struct Member Alignment中修改,默认是8字节。

2.在编码时,可以这样动态修改:#pragma pack .注意:是pragma而不是progma.五.针对字节对齐,我们在编程中如何考虑?如果在编程的时候要考虑节约空间的话,那么我们只需要假定结构的首地址是0,然后各个变量按照上面的原则进行排列即可,基本的原则就是把结构中的变量按照类型大小从小到大声明,尽量减少中间的填补空间.还有一种就是为了以空间换取时间的效率,我们显示的进行填补空间进行对齐,比如:有一种使用空间换时间做法是显式的插入reserved成员:struct A{ char a; char reserved[3];//使用空间换时间int b;};reserved成员对我们的程序没有什么意义,它只是起到填补空间以达到字节对齐的目的,当然即使不加这个成员通常编译器也会给我们自动填补对齐,我们自己加上它只是起到显式的提醒作用.六.字节对齐可能带来的隐患:代码中关于对齐的隐患,很多是隐式的。

比如在强制类型转换的时候。

例如:unsigned int i = 0x12345678;unsigned char *p=NULL;unsigned short *p1=NULL;p=&i;*p=0x00;p1=(unsigned short *)(p+1);*p1=0x0000;最后两句代码,从奇数边界去访问unsignedshort型变量,显然不符合对齐的规定。

在x86上,类似的操作只会影响效率,但是在MIPS或者sparc上,可能就是一个error,因为它们要求必须字节对齐.七.如何查找与字节对齐方面的问题:如果出现对齐或者赋值问题首先查看1. 编译器的big little端设置2. 看这种体系本身是否支持非对齐访问3. 如果支持看设置了对齐与否,如果没有则看访问时需要加某些特殊的修饰来标志其特殊访问操作。

本文来自CSDN博客,转载请标明出处:/aurora77/archive/2009/02/17/3901891.aspx二..什么是字节对齐,为什么要对齐?现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。

对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。

一些平台对某些特定类型的数据只能从某些特定地址开始存取。

比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。

比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit 数据。

显然在读取效率上下降很多。

二.字节对齐对程序的影响:先让我们看几个例子吧(32bit,x86环境,gcc编译器):设结构体如下定义:struct A{int a;char b;short c;};struct B{char b;int a;short c;};现在已知32位机器上各种数据类型的长度如下:char:1(有符号无符号同)short:2(有符号无符号同)int:4(有符号无符号同)long:4(有符号无符号同)float:4 double:8那么上面两个结构大小如何呢?结果是:sizeof(strcut A)值为8sizeof(struct B)的值却是12结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一个,B也一样;按理说A,B大小应该都是7字节。

相关文档
最新文档