Как использовать 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) Нераспределенный доступ к памяти: это определенное поведение или нет? [Что дублируется, но, может быть, с некоторой дополнительной информацией].