Как использовать alignas для замены пакета Pragma?
Я пытаюсь понять, как использовать alignas, мне интересно, может ли это быть заменой прагматическому пакету, я очень старался это проверить, но безуспешно. Используя gcc 4.8.1 ( http://ideone.com/04mxpI), я всегда получаю 8 байт для STestAlignas ниже, тогда как с пакетом прагмы это 5 байт. То, что я хотел бы добиться, это сделать, чтобы sizeof(STestAlignas) возвращал 5. Я попытался запустить этот код на clang 3.3 ( http://gcc.godbolt.org/), но получил ошибку:
Ошибка: запрошенное выравнивание меньше, чем минимальное выравнивание 8 для типа 'long' - чуть ниже использования alignas.
Так может быть, есть минимальное значение выравнивания для alignas?
ниже мой тестовый код:
#include <iostream>
#include <cstddef>
using namespace std;
#pragma pack(1)
struct STestPragmaPack {
char c;
long d;
} datasPP;
#pragma pack()
struct STestAttributPacked {
char c;
long d;
} __attribute__((packed)) datasAP;
struct STestAlignas {
char c;
alignas(char) long d;
} datasA;
int main() {
cout << "pragma pack = " << sizeof(datasPP) << endl;
cout << "attribute packed = " << sizeof(datasAP) << endl;
cout << "alignas = " << sizeof(datasA) << endl;
}
результаты для gcc 4.8.1:
pragma pack = 5
attribute packed = 5
alignas = 8
1 ответ
alignas
не может заменить #pragma pack
,
GCC принимает alignas
объявление, но по-прежнему сохраняет элемент должным образом выровненным: удовлетворяя самым строгим требованиям выравнивания (в этом случае выравнивание long
) также удовлетворяет указанному вами требованию.
Однако GCC слишком мягок, так как стандарт на самом деле явно запрещает это в §7.6.2, параграф 5:
Объединенный эффект всех спецификаторов выравнивания в объявлении не должен определять выравнивание, которое является менее строгим, чем выравнивание, которое потребовалось бы для объявляемого объекта, если бы все спецификаторы выравнивания были опущены (в том числе в других объявлениях).
Я полагаю, вы знаете, что работа с невыровненными или несогласованными данными сопряжена с рисками и требует затрат.
Например, получение неправильно выровненной структуры данных из 5 байтов требует больше времени, чем получение выровненной структуры данных из 8 байтов. Это потому, что, если ваши 5-дюймовые... байтовые данные не начинаются на одной из этих 4-байтовых границ, компьютер должен дважды прочитать память, а затем внутренне собрать 4 байта в один регистр " (1).
Работа с невыровненными данными требует большего количества математических операций и приводит к большему потреблению времени (и мощности) ЭБУ.
Учтите, что и C, и C++ задуманы как "дружественные к оборудованию" языки, что означает не только языки с "минимальным использованием памяти", но в основном языки, ориентированные на эффективность и скорость обработки. Выравнивание данных (когда это не является строго обязательным для "того, что мне нужно хранить") - это концепция, которая подразумевает другое: "во многих случаях программное и аппаратное обеспечение похожи на жизнь: для достижения лучших результатов требуются жертвы!".
Пожалуйста, подумайте также о том, чтобы спросить себя, не ошиблись ли вы. Что-то вроде: "меньшие / st структуры => более быстрая / st обработка". Если бы это было так, вы могли бы (полностью) ошибаться.
Но если мы предположим, что ваша точка зрения примерно такая: вас совсем не заботит эффективность, энергопотребление и скорость вашего программного обеспечения, а просто вы одержимы (из-за ограничений вашего оборудования или просто из-за теоретического интереса) в "минимуме использование памяти ", то, возможно, вам могут пригодиться следующие показания:
(1) Объявление, управление и доступ к невыровненной памяти в C++
(2) C Как избежать проблем с выравниванием
НО, пожалуйста, обязательно прочтите следующие:
(3) Что в стандарте говорится о доступе к невыровненной памяти?
Что перенаправляет на этот стандарт:
(4) http://eel.is/c++draft/basic.life
(5) Невыровненный доступ к памяти: это определенное поведение или нет?[Это дублируется, но, возможно, с некоторой дополнительной информацией].
К сожалению, выравнивание не гарантируется ни в C++11, ни в C++ 14.Но это эффективно и гарантировано в C++17.
Пожалуйста, посмотрите эту прекрасную работу Бартломея Филипека: