Типы POD всегда выровнены? - PullRequest
       25

Типы POD всегда выровнены?

3 голосов
/ 18 сентября 2008

Например, если я объявляю длинную переменную, могу ли я предположить, что она всегда будет выровнена по границе "sizeof (long)"? Так говорит онлайн-справка по Microsoft Visual C ++, но разве это стандартное поведение?

дополнительная информация:

а. Можно явно создать смещенное целое число (* bar):

char foo [5]

int * bar = (int *) (& foo [1]);

б. Очевидно, #pragma pack () влияет только на структуры, классы и объединения.

с. Документация MSVC гласит, что типы POD выровнены по соответствующим размерам (но всегда ли это или по умолчанию, и это стандартное поведение, я не знаю)

Ответы [ 6 ]

9 голосов
/ 18 сентября 2008

Как уже упоминали другие, это не является частью стандарта и оставлено на усмотрение компилятора так, как он считает нужным для рассматриваемого процессора. Например, VC может легко реализовать другие требования к выравниванию для процессора ARM, чем для процессоров x86.

Microsoft VC реализует то, что обычно называется естественным выравниванием, вплоть до размера, указанного в директиве #pragma pack или параметре командной строки / Zp. Это означает, что, например, любой тип POD с размером, меньшим или равным 8 байтам, будет выровнен на основе его размера. Все, что больше, будет выровнено по 8-байтовой границе.

Если важно, чтобы вы управляли выравниванием для разных процессоров и разных компиляторов, тогда вы можете использовать размер упаковки 1 и заполнить ваши структуры.

#pragma pack(push)
#pragma pack(1)    
struct Example
{
   short data1;     // offset 0
   short padding1;  // offset 2
   long data2;      // offset 4
};
#pragma pack(pop)

В этом коде переменная padding1 существует только для обеспечения естественного выравнивания data2.

Ответ на вопрос:

Да, это может легко привести к смещению данных. На процессоре x86 это не очень больно. На других процессорах это может привести к сбою или очень медленному выполнению. Например, процессор Alpha выдаст исключение процессора, которое будет обнаружено ОС. Затем ОС проверяет инструкцию и затем выполняет работу, необходимую для обработки выровненных данных. Затем исполнение продолжается. Ключевое слово __unaligned может использоваться в VC для обозначения невыровненного доступа для программ, отличных от x86 (т.е. для CE).

3 голосов
/ 18 сентября 2008

По умолчанию да. Однако его можно изменить с помощью pack () # pragma.

Я не верю, что стандарт C ++ предъявляет какие-либо требования в этом отношении и оставляет его на усмотрение.

1 голос
/ 18 сентября 2008

C и C ++ не требуют какого-либо выравнивания. Но x86 настоятельно предпочитает естественное выравнивание, и требуется для большинства других архитектур ЦП, и компиляторы, как правило, делают все возможное, чтобы процессоры были довольны. Поэтому на практике вы не увидите, чтобы компилятор генерировал неверно выровненные данные, если вы действительно не поверните его руку.

0 голосов
/ 18 сентября 2008

Как правило, это происходит потому, что чтение / запись в него происходит быстрее. Но почти у каждого компилятора есть переключатель, чтобы отключить это. В gcc ее -составить-таки. Для агрегатов они обычно выровнены и рассчитаны на основе требований к выравниванию каждого элемента в пределах.

0 голосов
/ 18 сентября 2008

Зависит от компилятора, прагм и уровня оптимизации. С помощью современных компиляторов вы также можете выбрать оптимизацию времени или пространства, что также может изменить выравнивание типов.

0 голосов
/ 18 сентября 2008

Да, все типы всегда выровнены, по крайней мере, к их требованиям к выравниванию.

Как могло быть иначе?

Но учтите, что тип sizeof () не совпадает с его выравниванием.

Вы можете использовать следующий макрос для определения требований выравнивания типа:

#define ALIGNMENT_OF( t ) offsetof( struct { char x; t test; }, test )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...