Перейти к содержанию
    

Указатель на невыровненную память

Доброго времени суток!

Предположим, что у нас есть упакованная структура данных:

struct Foo {
	uint8_t v1;
	uint16_t v2;
} __attribute__((packed));
Foo foo;

Поле foo.v2 расположено по невыровненному адресу и при работе с данным полем компилятор автоматически выполняет побайтовое копирование (и это правильно).

Теперь попробуем взять указатель на данное поле:

uint16_t *vPtr = &foo.v2;

Компилятор выдаст предупреждение: warning: taking address of packed member of 'Foo' may result in an unaligned pointer value (и это тоже правильно)

А существует ли такой атрибут, позволяющий брать невыровненный указатель, чтобы компилятор понимал, что с ним тоже нужно работать как с невыровненным?

что-то типа такого:

uint16_t *vPtr __attribute__((packed)) = &foo.v2;
*vPtr = 10;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Ivan. сказал:

А существует ли такой атрибут, позволяющий брать невыровненный указатель, чтобы компилятор понимал, что с ним тоже нужно работать как с невыровненным?

У IAR существует: __packed

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Ivan. сказал:

Поле foo.v2 расположено по невыровненному адресу и при работе с данным полем компилятор автоматически выполняет побайтовое копирование (и это правильно).

Не факт. Для ядер >= Cortex-M3 && <= Cortex-M7 это скорее неправильно. Правильно было бы использовать LDRH/STRH.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По этому правильнее одеть это на усмотрение компилятора. Он то точно знает можно ли брать 2 бита по нечетному адресу или нет. 

14 минут назад, jcxz сказал:

Не факт. Для ядер >= Cortex-M3 && <= Cortex-M7 это скорее неправильно. Правильно было бы использовать LDRH/STRH.

Это еще зависит от региона. Я столкнулся в M7, что в одном домене можно брать невыровненные данные, а в другом вылетает в hardfault

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Ivan. сказал:

По этому правильнее одеть это на усмотрение компилятора. Он то точно знает можно ли брать 2 бита по нечетному адресу или нет. 

Какие биты? О чём речь?

Компилятор знает, что Cortex-M умеет невыровненный доступ. Поэтому он использует LDR/STR/LDRH/STRH.

1 час назад, Ivan. сказал:

Это еще зависит от региона. Я столкнулся в M7, что в одном домене можно брать невыровненные данные, а в другом вылетает в hardfault

В каком "домене"? Какие данные (разрядность)? О чём речь?

CM7 умеет невыровненный доступ (если его преднамеренно не запрещать).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 минут назад, jcxz сказал:

Какие биты? О чём речь?

Байты конечно. опечатался

12 минут назад, jcxz сказал:

В каком "домене"? Какие данные (разрядность)? О чём речь?

Опять мы уходим в сторону. Вопрос не об этом

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как раз pakсed и упакует структуру без зазоров на выравнивание. Там ведь неравные переменные по ширине - 16 и 8, остается зазор, который будет устранен аттрибутом packed

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Читайте вопрос внимательно. Как присвоить указатель на невыровненные данные, чтобы компилятор работал с этим указателем как с невыровненным

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В cmsis_gcc.h есть макрос __UNALIGNED_UINT32(x) :

Цитата

struct __attribute__((packed)) T_UINT32 { uint32_t v; };

#define __UNALIGNED_UINT32(x)                  (((struct T_UINT32 *)(x))->v)

Если я правильно понял, так сделано потому что в gcc атрибут __attribute__((packed)) можно применять только к структурам, а не к произвольным типам.  Возможно, можно что-то подобное сделать для uint16_t ? В том же файле чуть ниже есть макросы __UNALIGNED_UINT16_READ и __UNALIGNED_UINT16_WRITE где подобным образом к данным обращаются.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 минут назад, arhiv6 сказал:

В cmsis_gcc.h есть макрос __UNALIGNED_UINT32(x) :

Если я правильно понял, так сделано потому что в gcc атрибут __attribute__((packed)) можно применять только к структурам, а не к произвольным типам.  Возможно, можно что-то подобно сделать для uint16_t ? В том же файле чуть ниже есть макросы __UNALIGNED_UINT16_READ и __UNALIGNED_UINT16_WRITE где подобным образом к данным обращаются.

Похоже, это действительно решение в GCC, а на strict aliasing они решили забить... Мда:sad:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообще нормальная практика предполагает все-таки выравнивание в структурах.

Грубо говоря, сначала укладываем 32б данные (float, long etc), потом парами 16б, потом уже обнобайтные.

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

(или себе будущему)

On 10/18/2023 at 8:52 PM, Ivan. said:

Читайте вопрос внимательно. Как присвоить указатель на невыровненные данные, чтобы компилятор работал с этим указателем как с невыровненным

привести к (uint8_t*), но это дурной стиль.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

36 минут назад, MrYuran сказал:

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

Вы щас серьезно?😆 А как быть с тем, что уже сделано предыдущим поколение разработчиков, причем, буквально повсюду?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...