AirDevil 0 19 октября, 2009 Опубликовано 19 октября, 2009 (изменено) · Жалоба Всем привет! u32 func(char * array, u32 * A) { *A = 2; return *A; } Иногда возникает такая проблема, если А не выравнена по слову, попадает смещенная величина. Вот пример: В самом начале: ____word___________wordA____ | 00 00 00 00 |____| 00 00 00 00 | Должно получиться после присваивания: ____word___________wordA____ | 00 00 00 00 |____| 02 00 00 00 | А получается так: ____word___________wordA____ | 00 00 00 02 |____| 00 00 00 00 | Кто как борет это? Компилятор GCC. Изменено 19 октября, 2009 пользователем AirDevil Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 19 октября, 2009 Опубликовано 19 октября, 2009 · Жалоба Для какой архитектуры компилятор? Вы что-то путаете. Для начала вы определитесь какой на вашем таргете порядок байт (big/little)endian. Поэкспериментируйте в отладчике. И всё встанет на свои места. А отсутствие выравнивания внутри стандартных встроенных типов данных быть не может никогда! Выравнивание есть всегда и оно зависит от разрядности таргета и от настроек компилятора и всяких там pragma pack для структур. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 19 октября, 2009 Опубликовано 19 октября, 2009 · Жалоба Кто как борет это? Первое и самое главное не писать "говнокод" работу которого компилятор не сможет проконтролировать. Второе, если уж где-то реально нужно, то контролировать полученный адрес на выравненность и использовать для таких случаев (или тупо всегда) копирование областей памяти. Для какой архитектуры компилятор? ARM, например. Не AVR, не x86.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AirDevil 0 19 октября, 2009 Опубликовано 19 октября, 2009 (изменено) · Жалоба Первое и самое главное не писать "говнокод" работу которого компилятор не сможет проконтролировать. Трудно не согласиться. Второе, если уж где-то реально нужно, то контролировать полученный адрес на выравненность и использовать для таких случаев (или тупо всегда) копирование областей памяти. В принципе и делал когда глюки были. Выравнивание с помощью memcpy и всё. Я думал, что возможно еще есть пути. Оказывается, что нет и вижу что делал правильно. С П А С И Б О ! ! ! Изменено 19 октября, 2009 пользователем AirDevil Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 19 октября, 2009 Опубликовано 19 октября, 2009 · Жалоба Первое и самое главное не писать "говнокод" работу которого компилятор не сможет проконтролировать. В чём "говнокодность" присваивания *A = 2 при условии, что A - это указатель на u32? Автор наверняка умолчал о хитром способе вызова функции - это да. А в приведённом коде не вижу никакого криминала. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 19 октября, 2009 Опубликовано 19 октября, 2009 · Жалоба при условии, что A - это указатель на u32 Да, это указатель на u32, но не выровненный, а находящийся, например, в каком-нибудь буфере передачи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 19 октября, 2009 Опубликовано 19 октября, 2009 (изменено) · Жалоба Да, это указатель на u32, но не выровненный, а находящийся, например, в каком-нибудь буфере передачи. Для этого в IARе нужно было всего-то объявить невыравненный тип u32_unalign и вообще не напрягаться #pragma pack(push, 1) typedef u32 u32_unalign; #pragma pack(pop) u32 func(u08 * array, u32_unalign * A) { u32 tmp = *(u32_unalign *)array; *A = tmp; return tmp; } Работает ли это в GCC ? Ессно изменив прагму. Изменено 19 октября, 2009 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 19 октября, 2009 Опубликовано 19 октября, 2009 · Жалоба Работает ли это в GCC ? Ессно изменив прагму. Например: typedef unsigned int u32_unalign __attribute__ ((aligned (1))); Все-же атрибуты веселее прагм в большинстве случаев. :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 19 октября, 2009 Опубликовано 19 октября, 2009 · Жалоба Для этого.. #pragma pack(push, 1) typedef u32 u32_unalign; #pragma pack(pop) Например: typedef unsigned int u32_unalign __attribute__ ((aligned (1))); Даже не знаю, сметься, плакать, или спросить где Вы оба берете такую траву? Можно я помолчу? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 19 октября, 2009 Опубликовано 19 октября, 2009 (изменено) · Жалоба От зараза, не сработала Я обычно через структуру или union работаю (в IARе), а тут решил "сэкономить" и даже не проверил. #pragma pack(push, 1) typedef union { float f; u32 l; u16 w[2]; u08 b[4]; } u32_unalign; #pragma pack(pop) Звиняюсь, за спешку. Но этот вариант уже точно правильно работает и при записи и при чтении невыравненных переменных (long/short/float). Хотя вопрос к тем, кто знает - почему "typedef u32 u32_unalign;" внутри прагмы не работает? Изменено 19 октября, 2009 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 19 октября, 2009 Опубликовано 19 октября, 2009 · Жалоба Но этот вариант уже точно правильно работает... Чем дальше в лес, тем больше дров :(. Сколько еще "идей"? Может лучше спать, а поутру почитать, что за прагма pack и для чего она годится? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 19 октября, 2009 Опубликовано 19 октября, 2009 (изменено) · Жалоба Чем дальше в лес, тем больше дров :(. Сколько еще "идей"? Может лучше спать, а поутру почитать, что за прагма pack и для чего она годится? :) Вы удивитесь, но она не только отключает выравнивание многобайтных переменных внутри структур/юнионов, но и организует побайтный (при pack(1)) доступ ко всем полям внутри структур/юнионов. Я проверил в ИАРе - при обращении к полю l например (в описанном мной юнионе) чтение и запись происходят побайтовые. Я так думаю, что автору темы именно это и надо было. Изменено 19 октября, 2009 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 19 октября, 2009 Опубликовано 19 октября, 2009 · Жалоба Хотя вопрос к тем, кто знает - почему "typedef u32 u32_unalign;" внутри прагмы не работает?Потому что Pragma directive | Description ------------------------------------------------------------------------------- pack | Specifies the alignment of structures and union members А отдельные переменные и так всегда выровнены. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 20 октября, 2009 Опубликовано 20 октября, 2009 · Жалоба Отдельные переменные не всегда выравнены. В посте у автора темы параметром передаётся ссылка на u32. Вполне "законно" можно передать туда адрес переменной u32, находящейся в структуре с невыравненными переменными. ИАР при этом выдаст варнинг, что это опасно. GCC не знаю выдаст или нет. Так вот, если бы можно было создать тип u32 с атрибутом побайтового обращения, то не пришлось бы извращаться с юнионом. Отсюда вопрос - можно ли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 20 октября, 2009 Опубликовано 20 октября, 2009 · Жалоба Вполне "законно" можно передать туда адрес переменной u32, находящейся в структуре с невыравненными переменными.Кто так поступает, тот сам себе "злобный буратино". А если уж приспичило, то передавать нужно char-овский указатель, а не long-овский и копировать побайтово. Собственно все то же самое, что делает memcpy, с которой у топикстартера все нормально работает. В принципе и делал когда глюки были. Выравнивание с помощью memcpy и всё. Я думал, что возможно еще есть пути. Оказывается, что нет и вижу что делал правильно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться