Поддерживают ли приведения указатели свойства выравнивания? - PullRequest
8 голосов
/ 21 мая 2019

Скажите, у меня есть выровненный массив

alignas(X) char arr[sizeof(X)];

это указатель

X * ptr = reinterpret_cast<X*>(arr);

гарантированно выровнено в соответствии с требованиями выравнивания X?

Кажется очевидным, что это так, однако это не кажется очевидным из стандарта C ++.

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

struct X
{
    int16_t a;
    int32_t b;
    int16_t c;
};

как это в памяти:

+-+-+-+-+-+-+-+-+
|a|a|b|b|b|b|c|c|
+-+-+-+-+-+-+-+-+
     ^
     aligned to 32-boundary

, чтобы объекты типа X были выровнены таким образом, чтобы заполнение не требовалось, и b одновременно выровнялось правильно по 32-битной границе. Заявление (N4713, § 6.6.5.1)

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

не нарушается этим, и я не вижу никаких других утверждений в стандарте, которые его нарушают.

Ответы [ 2 ]

2 голосов
/ 21 мая 2019

Ваша структура должна иметь экзотическое выравнивание: оно должно быть выровнено по 16 битам, но не выровнено по 32.Математически говоря, его адрес должен иметь форму 32 * n + 16, с n целым числом.

Это запрещено языком, 32-битное выравниваниедолжно удовлетворять 16-битному выравниванию.Иначе говоря, любая 16-битная выровненная структура должна вписываться в 32-битную выровненную область хранения, а ваша 16-битная выровненная структура - нет.См. [basic.align] / 5 :

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

1 голос
/ 21 мая 2019

Авторы Стандарта не стремились явно запретить то, что они считали невозможным. Если одна единица компиляции содержит структуру, подобную той, которую вы дали:

struct {
  uint16_t a;
  uint32_t b;
  uint16_t c;
} x;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...