align (C++)align (C++)

В Visual Studio 2015 и более поздних версиях alignas для управления выравниванием используйте стандартный описатель c++ 11.In Visual Studio 2015 and later, use the C++11 standard alignas specifier to control alignment. Дополнительные сведения см. в разделе Выравнивание.For more information, see Alignment.

Блок, относящийся только к системам MicrosoftMicrosoft Specific

Используйте __declspec(align(#)) для точного управления выравниванием пользовательских данных (например, статическими распределениями или автоматическими данными в функции).Use __declspec(align(#)) to precisely control the alignment of user-defined data (for example, static allocations or automatic data in a function).

СинтаксисSyntax

Декларатор __declspec (выровняйте ( # )) __declspec( align( # ) ) declarator

КомментарииRemarks

Написание приложений, использующих последние инструкции процессора, связано с некоторыми новыми ограничениями и проблемами.Writing applications that use the latest processor instructions introduces some new constraints and issues. Для многих новых инструкций требуются данные, которые выводятся по 16-байтным границам.Many new instructions require data that's aligned to 16-byte boundaries. Кроме того, путем согласования часто используемых данных с размером строки кэша процессора повышается производительность кэша.Additionally, by aligning frequently used data to the processor's cache line size, you improve cache performance. Например, если определена структура, размер которой меньше 32 байт, то может потребоваться 32 байтов, чтобы обеспечить эффективное кэширование объектов этого типа структуры.For example, if you define a structure whose size is less than 32 bytes, you may want 32 byte alignment to make sure that objects of that structure type are efficiently cached.

# значение выравнивания.# is the alignment value. Допустимые записи — целые степени двух значений от 1 до 8192 (байты), например 2, 4, 8, 16, 32 или 64.Valid entries are integer powers of two from 1 to 8192 (bytes), such as 2, 4, 8, 16, 32, or 64. declarator — Это данные, которые объявляются как согласованные.declarator is the data that you're declaring as aligned.

Сведения о том, как вернуть значение типа size_t , которое является требованием выравнивания для типа, см. в разделе alignof .For information about how to return a value of type size_t that is the alignment requirement of the type, see alignof. Сведения об объявлении несогласованных указателей при нацеливании на 64-разрядные процессоры см. в разделе __unaligned .For information about how to declare unaligned pointers when targeting 64-bit processors, see __unaligned.

Можно использовать __declspec(align(#)) при определении struct , union или class , или при объявлении переменной.You can use __declspec(align(#)) when you define a struct, union, or class, or when you declare a variable.

Компилятор не гарантирует или не пытается сохранить атрибут выравнивания данных во время операции копирования или преобразования данных.The compiler doesn't guarantee or attempt to preserve the alignment attribute of data during a copy or data transform operation. Например, memcpy может скопировать структуру, объявленную с __declspec(align(#)) , в любое расположение.For example, memcpy can copy a struct declared with __declspec(align(#)) to any location. Обычные распределителя (например, malloc C++ operator new и распределителя Win32) обычно возвращают память, которая не полностью соответствует __declspec(align(#)) структурам или массивам структур.Ordinary allocators (for example, malloc, C++ operator new, and the Win32 allocators) typically return memory that isn't sufficiently aligned for __declspec(align(#)) structures or arrays of structures. Чтобы гарантировать, что назначение копирования или операции преобразования данных будет правильно согласовано, используйте _aligned_malloc .To guarantee that the destination of a copy or data transformation operation is correctly aligned, use _aligned_malloc. Или напишите собственный распределитель.Or, write your own allocator.

Нельзя указать выравнивание для параметров функции.You can't specify alignment for function parameters. При передаче данных с атрибутом выравнивания по значению в стеке его выравнивание регулируется соглашением о вызовах.When you pass data that has an alignment attribute by value on the stack, its alignment is controlled by the calling convention. Если в вызываемой функции важно выравнивание данных, скопируйте параметр в правильно выровненную память перед использованием.If data alignment is important in the called function, copy the parameter into correctly aligned memory before use.

Без этого __declspec(align(#)) компилятор обычно выровнять данные по естественным границам, исходя из целевого процессора и размера данных, до 4-байтовых границ на 32-разрядных процессорах и 8-байтовых границ на 64-разрядных процессорах.Without __declspec(align(#)), the compiler generally aligns data on natural boundaries based on the target processor and the size of the data, up to 4-byte boundaries on 32-bit processors, and 8-byte boundaries on 64-bit processors. Данные в классах или структурах выравниваться в классе или структуре на минимальном уровне естественного выравнивания и текущем параметре упаковки (от #pragma pack или /Zp параметра компилятора).Data in classes or structures is aligned in the class or structure at the minimum of its natural alignment and the current packing setting (from #pragma pack or the /Zp compiler option).

В этом примере демонстрируется использование __declspec(align(#)):This example demonstrates the use of __declspec(align(#)):

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

Теперь этот тип содержит 32-разрядный атрибут выравнивания.This type now has a 32-byte alignment attribute. Это означает, что все статические и автоматические экземпляры начинаются на границе 32 байта.It means that all static and automatic instances start on a 32-byte boundary. Дополнительные типы структуры, объявленные с этим типом в качестве члена, сохраняют атрибут выравнивания этого типа, то есть любая структура с Str1 элементом имеет атрибут выравнивания не менее 32.Additional structure types declared with this type as a member preserve this type's alignment attribute, that is, any structure with Str1 as an element has an alignment attribute of at least 32.

Здесь, sizeof(struct Str1) равно 32.Here, sizeof(struct Str1) is equal to 32. Это означает, что если создается массив Str1 объектов, а основание массива составляет 32 байт, то каждый элемент массива также имеет значение, равное 32 байт.It implies that if an array of Str1 objects is created, and the base of the array is 32-byte aligned, each member of the array is also 32-byte aligned. Чтобы создать массив, базовый объект которого правильно соответствует динамической памяти, используйте _aligned_malloc .To create an array whose base is correctly aligned in dynamic memory, use _aligned_malloc. Или напишите собственный распределитель.Or, write your own allocator.

sizeof Значением для любой структуры является смещение последнего элемента, а также его размер, округленный до ближайшего числа, кратного наибольшему значению выравнивания элемента или целому значению выравнивания структуры, в зависимости от того, какое значение больше.The sizeof value for any structure is the offset of the final member, plus that member's size, rounded up to the nearest multiple of the largest member alignment value or the whole structure alignment value, whichever is larger.

Компилятор использует эти правила для выравнивания структуры:The compiler uses these rules for structure alignment:

  • Если выравнивание не переопределяется с помощью __declspec(align(#)), выравнивание скалярного члена структуры — это его минимальный размер и текущая упаковка.Unless overridden with __declspec(align(#)), the alignment of a scalar structure member is the minimum of its size and the current packing.

  • Если выравнивание не переопределяется с помощью __declspec(align(#)), выравнивание структуры — это максимальное число отдельных выравниваний членов.Unless overridden with __declspec(align(#)), the alignment of a structure is the maximum of the individual alignments of its member(s).

  • Элемент структуры помещается со смещением от начала его родительской структуры, которая является наименьшей, кратным значению смещения конца предыдущего элемента.A structure member is placed at an offset from the start of its parent structure that's the smallest multiple of its alignment greater than or equal to the offset of the end of the previous member.

  • Размер структуры — это наименьшее число, кратное ее выравниванию, больше или равное смещению в конце его последнего члена.The size of a structure is the smallest multiple of its alignment greater than or equal to the offset of the end of its last member.

__declspec(align(#)) может только увеличить ограничения выравнивания.__declspec(align(#)) can only increase alignment restrictions.

Дополнительные сведения см. в разделе:For more information, see:

Примеры выровняйтеalign Examples

В следующих примерах показано, как __declspec(align(#)) влияет на размер и выравнивание структур данных.The following examples show how __declspec(align(#)) affects the size and alignment of data structures. В примерах допускаются следующие определения.The examples assume the following definitions:

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

В этом примере структура S1 определена с помощью __declspec(align(32)).In this example, the S1 structure is defined by using __declspec(align(32)). Все случаи использования S1 для определения переменных или в объявлениях других типов выравниваются по 32 байтам.All uses of S1 for a variable definition or in other type declarations are 32-byte aligned. sizeof(struct S1) возвращает значение 32, а S1 имеет 16 байтов заполнения после 16 байтов, необходимых для удержания четырех целых чисел.sizeof(struct S1) returns 32, and S1 has 16 padding bytes following the 16 bytes required to hold the four integers. Каждый int элемент требует 4-байтового выравнивания, но выравнивание самой структуры объявляется как 32.Each int member requires 4-byte alignment, but the alignment of the structure itself is declared to be 32. Затем общее выравнивание составляет 32.Then the overall alignment is 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).In this example, sizeof(struct S2) returns 16, which is exactly the sum of the member sizes, because that is a multiple of the largest alignment requirement (a multiple of 8).

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

В следующем примере sizeof(struct S3) возвращает 64.In the following example, sizeof(struct S3) returns 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 байтам.In this example, notice that a has the alignment of its natural type, in this case, 4 bytes. Однако значение S1 должно быть выровнено по 32-байтовой границе.However, S1 must be 32-byte aligned. Далее следует 28 байтов заполнения a , чтобы оно s1 начиналось со смещения 32.28 bytes of padding follow a, so that s1 starts at offset 32. S4 затем наследует требование выравнивания S1 , поскольку оно является самым большим требованием к выравниванию в структуре.S4 then inherits the alignment requirement of S1, because it's the largest alignment requirement in the structure. sizeof(struct S4) возвращает 64.sizeof(struct S4) returns 64.

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

Следующие три объявления переменных также используют __declspec(align(#)).The following three variable declarations also use __declspec(align(#)). В каждом случае переменная должна быть выровнена по 32 байтам.In each case, the variable must be 32-byte aligned. В массиве базовый адрес массива, а не каждый элемент массива составляет 32 байт.In the array, the base address of the array, not each array member, is 32-byte aligned. sizeof Значение для каждого элемента массива не изменяется при использовании __declspec(align(#)) .The sizeof value for each array member is unaffected when you use __declspec(align(#)).

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

Для выравнивания каждого члена массива нужно использовать следующий код:To align each member of an array, code such as this should be used:

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

Обратите внимание, что в этом примере выравнивание самой структуры и первого элемента работают одинаково:In this example, notice that aligning the structure itself and aligning the first element have the same effect:

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

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

S6 и S7 имеют одинаковые характеристики выравнивания, выделения и размера.S6 and S7 have identical alignment, allocation, and size characteristics.

В этом примере выравнивание начальных адресов a, b, c и d — соответственно 4, 1, 4, и 1.In this example, the alignment of the starting addresses of a, b, c, and d are 4, 1, 4, and 1, respectively.

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

Выравнивание при выделении памяти в куче зависит от того, какая функция выделения вызвана.The alignment when memory is allocated on the heap depends on which allocation function is called. Например, если используется malloc, результат зависит от размера операнда.For example, if you use malloc, the result depends on the operand size. Если аргумент arg >= 8, возвращается память размером 8 байт.If arg >= 8, the memory returned is 8 byte aligned. Если аргумент arg < 8, то при выравнивании возвращаемой памяти первая степень числа 2 меньше аргумента будет первой.If arg < 8, the alignment of the memory returned is the first power of 2 less than arg. Например, если используется malloc(7) , выравнивание составляет 4 байта.For example, if you use malloc(7), the alignment is 4 bytes.

Определение новых типов с помощью __declspec(align(#))Defining new types with __declspec(align(#))

Можно определить тип с характеристикой выравнивания.You can define a type with an alignment characteristic.

Например, можно определить struct с помощью значения выравнивания следующим образом:For example, you can define a struct with an alignment value this way:

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

Теперь aType и bType имеют одинаковый размер (8 байт), но переменные типа bType — 32 байт.Now, aType and bType are the same size (8 bytes) but variables of type bType are 32-byte aligned.

Выровняйте данные в локальном хранилище потокаAligning data in thread local storage

Статическое локальное хранилище потока (TLS), созданное с помощью атрибута __declspec(thread) и помещенное в раздел TLS образа, обеспечивает выравнивание так же, как стандартные статические данные.Static thread-local storage (TLS) created with the __declspec(thread) attribute and put in the TLS section in the image works for alignment exactly like normal static data. Для создания данных TLS операционная система выделяет память в размере раздела TLS и сохраняет атрибут выравнивания раздела TLS.To create TLS data, the operating system allocates memory the size of the TLS section and respects the TLS section alignment attribute.

В этом примере показаны различные способы помещения выровненных данных в локальное хранилище потока.This example shows various ways to place aligned data into thread local storage.

// 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;

Принцип align работы с упаковкой данныхHow align works with data packing

/ZpПараметр компилятора и pack директива pragma имеют воздействие на данные упаковки для членов структуры и объединения.The /Zp compiler option and the pack pragma have the effect of packing data for structure and union members. В этом примере показано /Zp , как и __declspec(align(#)) совместно работать:This example shows how /Zp and __declspec(align(#)) work together:

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

В следующей таблице перечислены смещения каждого элемента в различных /Zp значениях (или #pragma pack ), показывающие, как эти два взаимодействуют.The following table lists the offset of each member under different /Zp (or #pragma pack) values, showing how the two interact.

ПеременнаяVariable /Zp1/Zp1 /Zp2/Zp2 /Zp4/Zp4 /Zp8/Zp8
аa 00 00 00 00
bb 11 22 22 22
сc 33 44 44 88
dd 3232 3232 3232 3232
йe 4040 4040 4040 4040
ff 4141 4242 4444 4848
sizeof(S)sizeof(S) 6464 6464 6464 6464

Дополнительные сведения см. в разделе /Zp (выравнивание членов структуры).For more information, see /Zp (Struct Member Alignment).

Смещение объекта зависит от смещения предыдущего объекта и от текущего параметра упаковки, если у объекта нет атрибута __declspec(align(#)). Если же такой атрибут есть, то выравнивание зависит от смещения предыдущего объекта и от значения __declspec(align(#)) объекта.The offset of an object is based on the offset of the previous object and the current packing setting, unless the object has a __declspec(align(#)) attribute, in which case the alignment is based on the offset of the previous object and the __declspec(align(#)) value for the object.

Завершение блока, относящегося только к системам МайкрософтEND Microsoft Specific

См. такжеSee also

__declspec
Обзор соглашений ABI ARMOverview of ARM ABI Conventions
Программные соглашения для 64-разрядных системx64 software conventions