Как использовать 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
[26.08.2019]
Похоже, что в этой теме есть движение за стандартизацию. Предложение p1112 - Языковая поддержка для управления макетом класса - предлагает добавить (среди прочего) атрибут [[layout(smallest)]]
, который должен переупорядочивать членов класса, чтобы сделать затраты на выравнивание настолько малыми, насколько это возможно (что является обычной техникой для программистов). - но это часто убивает читаемость определения класса). Но это не равно тому, что делает прагма (пакет)!
Ответы
Ответ 1
alignas
не может заменить #pragma pack
.
GCC принимает объявление alignas
, но все равно удерживает элемент правильно выровненным: удовлетворяющий строжайшему требованию выравнивания (в этом случае выравнивание long
) также удовлетворяет указанному вами требованию.
Однако GCC слишком мягкий, поскольку стандарт фактически прямо запрещает это в пункте 7.6.2, параграф 5:
Комбинированный эффект всех спецификаторов выравнивания в объявлении не должен указывать выравнивание, которое является менее строгим, чем выравнивание, которое требуется для объявляемого объекта, если все указатели выравнивания были опущены (в том числе в других объявлениях).
Ответ 2
К сожалению, выравнивание не гарантируется ни в С++ 11, ни в С++ 14.
Но это гарантировано в С++ 17.
Пожалуйста, проверьте эту отличную работу от Bartlomiej Filipek:
https://www.bfilipek.com/2019/08/newnew-align.html
Ответ 3
Я полагаю, вы знаете, что работа с не выровненными или не выровненными данными сопряжена с риском и сопряжена с расходами.
Например, получение неправильно выровненной структуры данных из 5 байтов более затратно по времени, чем извлечение выровненной по 8 байтов структуры. Это связано с тем, что если ваши 5 "... байтовые данные не начинаются с одной из этих 4-байтовых границ, компьютер должен прочитать память дважды, а затем собрать 4 байта в один регистр внутри" (1).
Работа с невыровненными данными требует больше математических операций и приводит к большему потреблению времени (и мощности) ЭБУ.
Пожалуйста, учтите, что и C, и C++ заданы как "дружественные к оборудованию" языки, что означает не только языки "минимального использования памяти", но в основном языки, ориентированные на эффективность и быстроту обработки. Выравнивание данных (когда это не является строго обязательным для "того, что мне нужно хранить") - это концепция, которая подразумевает другое: "во многих случаях программное и аппаратное обеспечение похоже на жизнь: вам нужны жертвы, чтобы достичь лучших результатов!".
Пожалуйста, подумайте над тем, чтобы спросить себя, не ошиблись ли вы. Что-то вроде: "меньшие /st структуры => более быстрая /st обработка". Если бы это было так, вы могли бы (полностью) ошибаться.
Но если мы предполагаем, что ваша точка зрения примерно такая: вас совершенно не волнует эффективность, энергопотребление и скорость вашего программного обеспечения, а просто вы одержимы (из-за ограничений вашего оборудования или просто из-за теоретического интереса) в "минимуме" использование памяти ", тогда, возможно, вам пригодятся следующие данные:
(1) Объявление, управление и доступ к невыровненной памяти в C++
(2) C Как избежать проблем с выравниванием
НО, пожалуйста, обязательно прочитайте следующее:
(3) Что говорится в стандарте о доступе к памяти без выравнивания?
Который перенаправляет на этот стандарт, отсекается:
(4) http://eel.is/C++draft/basic.life#1
(5) Нераспределенный доступ к памяти: это определенное поведение или нет? [Что дублируется, но, может быть, с некоторой дополнительной информацией].