Поделиться через


выравнивание (C++)

Только для систем Microsoft

Используйте __declspec(align(#)) точно контролировать выравнивание определяемых пользователем данных (например, статические распределения или автоматические данные в функции).

Дополнительные сведения о выравнивании см. Выравнивание по данным windows на IPF, x86 и x64.

__declspec( align( # ) ) declarator

Заметки

Приложения, которые используют последние инструкции вводят новые ограничения и процессора некоторые проблемы.В частности, множество новых инструкций требуют, чтобы данные нужно выравнивать до 16 границ байта.Кроме того, выравнивание часто используемые данные на размер линии кэша конкретного процессора, то производительность повысится кэша.Например, если указать структуру, размер которых меньше 32 байт, можно выравнивать его до 32 байт, чтобы убедиться, что объекты этого типа структуры эффективно кэшируются.

# значение выравнивания.Допустимые записи степень целым числом от 1 до 8192 (2 байт), например 2, 4, 8, 16, 32 или 64.declarator данные, объявленные как выравнивается по нижнему краю.

См. __alignof дополнительные сведения о том, как возвращать значение типа size_t это требование к выравниванию типа.и __unaligned сведения об объявлении бесподстроечные указатели, предназначенных для 64-разрядных процессоров - 64.

Можно использовать __declspec(align(#)) при указании a struct" unionили classили, если вы объявите переменную.

Без __declspec(align(#))Visual C++ выравнивание данных в естественных диапазоне, в зависимости от размера данных, например 4 целого числа байтов в диапазоне от 4 байт до 8 байт аналогов в диапазоне 8 байта.Данные в классах или структурах выравниваются в пределах класса или структуры по крайней мере его естественных выравнивания и текущего значения параметра упаковки (из #pragma pack или /Zp параметр компилятора).

Нельзя задать выравнивание для параметров функции.

Примеры.

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

Этот тип теперь имеет атрибут выравнивания 32 байт, что все экземпляры должны начинаться на границе байта 32.Дополнительные типы структур, объявленные с этим типом, что и член сохраняют этот атрибут типа выравнивания, т е любую структуру Str1 так как элемент будет иметь атрибут выравнивания по крайней мере 32.

Итоги вышесказанного приведены ниже.

  • Если не переопределено с __declspec(align(#))выравнивание члена структуры, скалярных минимум его размера и текущей упаковки.

  • Если не переопределено с __declspec(align(#))выравнивание структуры, до отдельных выравниваний его членов.

  • Элемент структуры помещается в позиции с начала его родительской структуры, наименьшая кратной его выравнивания больше или равно смещению конца предыдущего элемента.

  • Размер структуры наименьшая кратной его большого выравнивания больше или равно смещение конца своего последнего элемента.

Обратите внимание, что sizeof(struct Str1) равно 32, то, что, если создается массив объектов Str1 и основе массива байт выравниванный 32, то каждый элемент массива также становится выравниванным 32 байт.Для создания массива основе которого используется правильно выравнивается _aligned_mallocили написать собственный механизм распределения.Обратите внимание, что обычные allocators, например mallocВ C++ оператор newallocators Win32 и возвращают память, скорее всего, не выравнивает declspec(align(#)) структуры или массивы структур.

sizeof значение для любой структуры смещение последнего элемента, плюс размер этого элемента округленный до ближайшего числа, кратного самого большого значения выравнивания элемента или значения выравнивания структуры целиком, большее из значений.

__declspec(align(#)) допускается только увеличить ограничения выравнивания.

Дополнительные сведения см. в следующих разделах.

  • выравнивание примеры

  • Определение новых типов с помощью __declspec (выравнивание (#))

  • Выравнивание данных в локальном хранилище потока

  • Например, выравнивание работает с упаковкой данных

  • Примеры выравнивания структуры (только для 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 байтов, необходимое для хранения 4 целого числа.Каждое 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 байт.28 Байтов заполнения выполните 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
};

Следующие 3 объявления переменных также используют __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 имеют идентичные выравнивание, распределение и характеристики размера.

В следующем примере выравнивание начальной адресов a, b, c и d 4, 1, 4 и 1 соответственно.

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

Выравнивание если память выделена на зависит от функций выделения кучи, которые вызывают.Например, при использовании malloc, зависит от результата размер операнда.If аргумент Выравнивание >= 8, будет выравниванным 8 байт.If аргумент < 8, выравнивание будет первой мощью 2 меньше аргумент.Например, при использовании malloc (7), выравнивание 4 байта.

Определение новых типов с помощью __declspec (выравнивание (#))

Можно определить тип с характеристикой выравнивания.

Например, можно указать a 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;

Например, выравнивание работает с упаковкой данных

/Zp и параметр компилятора pack директива pragma действует упаковка структуры данных и члены объединения.В этом примере демонстрируется /Zp и __declspec(align(#)) рабочий совместно.

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

В следующей таблице перечислены смещение каждого элемента в различных /Zp (или #pragma pack) значения, указывающее, как интерактивное 2.

Переменная

/Zp1

/Zp2

/Zp4

/Zp8

объект

0

0

0

0

в

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 (Выравнивание члена структуры).

Таким образом, смещение объекта основано на некотором смещении от предыдущего объекта и текущего значения параметра упаковки, если объект не будет иметь a __declspec(align(#)) атрибут, и в этом случае выравнивания основано на некотором смещении от предыдущего объекта и __declspec(align(#))значение объекта.

См. также

Ссылки

__declspec