对齐(C++)

Microsoft 专用

使用 __declspec(align(#)) 精确控制用户定义的数据的对齐方式 (例如,静态分配或自动数据在函数)。

有关对齐方式的更多信息,请 Windows Data Alignment on IPF, x86, and x64参见。

__declspec( align( # ) ) declarator

备注

使用最新的处理器指令引入这些新约束编写应用程序和问题。 具体而言,许多新命令要求必须对齐数据为 16 字节边界。 另外,可以对齐一个特定处理器的缓存行范围的常用数据,从而可以改进缓存性能。 例如,因此,如果您定义范围少于 32 个字节的结构,您可能希望对齐到 32 个字节确保有效地缓存该结构类型的对象。

# 是对齐值。 有效项是整数幂的两个从 1 到 8192 (字节),如 2, 4, 8, 16, 32 或 64。 declarator 是您声明为对齐数据。

请参见 __alignof 有关如何返回都是类型的对齐 " 要求类型 size_t 的值的信息。 有关如何的 __unaligned 声明对齐指针的信息,这些扩展在面向 64 位处理器时。

可以使用 __declspec(align(#)) ,在定义 struct、 union或 class时,或者,在声明变量时。

不 __declspec(align(#)), Visual C++ 对齐有关根据数据范围的本机分界线的数据,如 4 字节边界的 4 字节整数和的 8 字节边界 8 字节的二进制文件。 在类或结构的数据在类或结构中对齐在最小其自然对齐和当前 pack 设置 (从 #pragma pack/Zp 编译器选项)。

不能为函数参数指定对齐。

例如:

__declspec(align(32)) struct Str1{
   int a, b, c, d, e;
};

此类型现在具有 32 字节对齐方式属性,这意味着所有实例。 32 字节边界必须启动。 附加的结构类型是用此类型用作成员保留此类型的对齐方式属性,也就是说,使用 Str1 的结构作为元素将具有对齐方式属性至少为 32。

总结如下:

  • 除非重写操作 __declspec(align(#)),标量结构成员对齐方式是其大小和当前 pack 最小值。

  • 除非重写操作 __declspec(align(#)),结构的对齐是其成员的各个对齐的最大值。

  • 结构成员置于偏移量最初是其对齐的最小多个大于或等于这个以上成员的末尾偏移量其父结构。

  • 结构的范围非常小的倍数其对齐更大大于或等于其前成员的末尾的偏移量。

请注意 sizeof(struct Str1) 是等于 32,,这样,如果数组 Str1 创建对象时,因此,该数组的基础是 32 字节对齐的,那么数组的每个成员也将是对齐的 32 字节。 若要创建基础正确对齐的数组,请使用 _aligned_malloc或编写拥有分配器。 请注意常规分配器,例如 malloc, C++ new 运算符和 Win32 分配器返回不会为declspec(align(#)) 结构或结构数组完全可能对齐的内存。

所有结构的 sizeof 值是最终成员的偏移量,以及该成员的范围,舍入最大的成员对齐值或整个结构对齐值的最近多个,后者会更大。

__declspec(align(#)) 只能增加对齐限制。

有关更多信息,请参见:

  • 对齐示例

  • 定义具有 __declspec 的新类型 (align (#)

  • 在中对齐线程本地存储的数据

  • 如何将 Works 与数据包

  • 结构对齐示例(针对 x64)

对齐示例

下面的示例演示 __declspec(align(#)) 如何影响数据结构的大小和对齐方式。 示例假定以下定义:

#define CACHE_LINE  32
#define CACHE_ALIGN __declspec(align(CACHE_LINE))

在下面的示例中, S1 结构定义与 __declspec(align(32))。 为 S1的所有用法,对于可变定义或其他类型声明,则确保此结构数据是对齐的 32 字节。 sizeof(struct S1) 返回 32,因此, S1 有 16 个字节填充所需的 16 个字节之后包含四个整数。 每个 int 成员需要 4 字节对齐,但是,结构的对齐方式声明为 32,因此,整体对齐为 32。

struct CACHE_ALIGN S1 { // cache align all instances of S1
   int a, b, c, d;
};
struct S1 s1;   // s1 is 32-byte cache aligned

在下面的示例中, sizeof(struct S2) 将返回 16,恰好为成员大小总和,,因为这恰好是最大的对齐要求 (多线程的多线程的 8)。

__declspec(align(8)) struct S2 {
   int a, b, c, d;
};

在下面的示例中, sizeof(struct S3) 返回 64。

struct S3 {
   struct S1 s1;   // S3 inherits cache alignment requirement
                  // from S1 declaration
   int a;         // a is now cache aligned because of s1
                  // 28 bytes of trailing padding
};

在下面的示例中,请注意 a 具有自然类型的仅对齐方式,在这种情况下, 4 字节。 但是, S1 必须是对齐的 32 字节。 二十八个字节填充遵循 a,因此, s1 开始在偏移量 32。 ,因为它是在框架中,的最大的对齐要求S4 然后继承 S1的对齐要求。 sizeof(struct S4) 返回 64。

struct S4 {
   int a;
   // 28 bytes padding
    struct S1 s1;      // S4 inherits cache alignment requirement of S1
};

以下三个变量声明还使用 __declspec(align(#))。 在每种情况下,变量必须是对齐的 32 字节。 对于数组,该数组,而不是每个数组成员的基址,是对齐的 32 字节。 每个数组成员的 sizeof 值不受影响使用 __declspec(align(#))。

CACHE_ALIGN int i;
CACHE_ALIGN int array[128];
CACHE_ALIGN struct s2 s;

对齐数组的每个单个成员,请如下代码应使用:

typedef CACHE_ALIGN struct { int a; } S5;
S5 array[10];

在下面的示例中,请注意对齐结构方式,以及对齐第一个元素完全相同的:

CACHE_ALIGN struct S6 {
   int a;
   int b;
};

struct S7 {
   CACHE_ALIGN int a;
               int b;
};

S6 和 S7 具有相同的对齐、分配和大小属性。

在下面的示例中,的起始地址的对齐方式, b、 c、 d 分别为 4, 1, 4 和 1,。

void fn() { 
   int a;
   char b;
   long c;
   char d[10]
} 

对齐方式,如果内存堆中分配了取决于个分配函数调用。 例如,如果您使用的是, malloc,该结果取决于操作数大小。 如果 arg AMP_GT= 8,对齐方式将为 8 字节对齐的。 如果 arg AMP_LT 8,对齐方式比 arg将在第一次幂的 2。 例如,如果您使用的是, malloc (7), " 对齐 " 为 4 字节。

定义具有 __declspec 的新类型 (align (#)

可以定义具有对齐特性的类型。

例如,可以定义与对齐值的 struct如下所示:

struct aType {int a; int b;};
typedef __declspec(align(32)) struct aType bType;

现在, aType 和 bType 大小相同 (8 字节),但类型 bType 的变量将是对齐的 32 字节。

在中对齐线程本地存储的数据

在 TLS 部分创建 __declspec(thread) 属性和放置的静态线程本地存储 (TLS)在图像工作的对齐方式与常规静态数据。 操作系统之间传递数据分配 TLS 部分的大小和保留 TLS 节对齐方式属性创建 TLS 数据。

下面的示例演示各种方式将对齐数据到线程本地存储区。

// put an aligned integer in TLS
__declspec(thread) __declspec(align(32)) int a;   

// define an aligned structure and put a variable of the struct type
// into TLS
__declspec(thread) __declspec(align(32)) struct F1 { int a; int b; } a;

// create an aligned structure 
struct CACHE_ALIGN S9 {
   int a;
   int b;
};
// put a variable of the structure type into TLS
__declspec(thread) struct S9 a;

如何将 Works 与数据包

/Zp 编译器选项和 pack 批注具有 pack 数据的效果结构和联合的成员。 此示例演示 /Zp 和 __declspec(align(#)) 如何:

struct S {
   char a;
   short b;
   double c;
   CACHE_ALIGN double d;
   char e;
   double f;
};

下表列出了如何偏移量每个成员在各种 /Zp (或 #pragma pack) 值下,显示两个交互。

变量

/Zp1

/Zp2

/Zp4

/Zp8

a

0

0

0

0

b

1

2

2

2

c

3

4

4

8

d

32

32

32

32

e

40

40

40

40

f

41

42

44

48

sizeof(S)

64

64

64

64

有关更多信息,请参见 /Zp(结构成员对齐)

因此,对象的偏移量根据以前的对象的偏移量和设置当前的 pack,该源,除非对象具有 __declspec(align(#)) 属性,否则,在对齐基于以前的对象的偏移量和对象的情况下 __declspec(align(#))值。

请参见

参考

__declspec