Вопросы | c

Когда следует использовать абстракцию типов во встроенных системах

Вопрос

itj | 1543 просмотров | рейтинг: 3

Я работал над несколькими различными встроенными системами. Все они использовали typedef (или #defines) для таких типов, как UINT32. Это хорошая методика, так как она сообщает программисту размер шрифта и дает вам больше шансов на переполнение и т. Д. Но в некоторых системах вы знаете, что компилятор и процессор не будут меняться на протяжении всего проекта. Итак, что должно повлиять на ваше решение о создании и реализации конкретных типов проектов? РЕДАКТИРОВАТЬ Я думаю, что мне удалось потерять суть моего вопроса, и, возможно, это действительно два. При встроенном программировании вам могут потребоваться типы определенного размера для интерфейсов, а также для работы с ограниченными ресурсами, такими как ОЗУ. Этого нельзя избежать, но вы можете использовать базовые типы из компилятора. Для всего остального типы имеют меньшее значение. Вы должны быть осторожны, чтобы не вызвать переполнение и, возможно, должны следить за использованием регистров и стеков. Что может привести вас к UINT16, UCHAR. Однако использование таких типов, как UCHAR, может добавить компилятор 'fluff'. Поскольку регистры обычно больше, некоторые компиляторы могут добавлять код, чтобы принудительно преобразовать результат в тип.

 я ++; 
может стать
 ДОБАВИТЬ РЕГ, 1
AND REG, 0xFF 
что не нужно. Поэтому я думаю, что мой вопрос должен был быть: учитывая ограничения встроенного программного обеспечения, какую политику лучше всего установить для проекта, над которым будут работать многие люди, не все из которых будут иметь одинаковый опыт.



Ответы

Bernard

+ 1 -
Согласованность, удобство и удобочитаемость. UINT32 гораздо более читабелен и доступен для записи, чем unsigned long long, что является эквивалентом для некоторых систем. Кроме того, компилятор и процессор могут быть исправлены на время существования проекта, но код этого проекта может найти новую жизнь в другом проекте. В этом случае наличие согласованных типов данных очень удобно.  


Chris Hanson

+ 7 -
Стандарт C99 имеет ряд стандартных размерных целочисленных типов. Если вы можете использовать компилятор, который поддерживает C99 (gcc поддерживает), вы найдете их в <stdint.h> и можете просто использовать их в своих проектах. Кроме того, во встроенных проектах может быть особенно важно использовать типы как своего рода страховочную сетку для таких вещей, как преобразование единиц. Если вы можете использовать C ++, я понимаю, что есть некоторые библиотеки модулей, которые позволяют вам работать в физических единицах, определенных системой типов C ++ (с помощью шаблонов), которые компилируются как операции с базовыми скалярными типами. Например, эти библиотеки не позволят вам добавить distance_t в mass_t, потому что единицы не выстраиваются в очередь; вы на самом деле получите ошибку компилятора. Даже если вы не можете работать на C ++ или другом языке, который позволяет вам писать код таким образом, вы можете, по крайней мере, использовать систему типов C, чтобы помочь вам ловить подобные ошибки на глаз. (На самом деле это было первоначальное намерение венгерской нотации Симони.) То, что компилятор не будет кричать на вас за добавление meter_t в gram_t, не означает, что вы не должны этого делать. Не используйте такие типы. Обзоры кода будут гораздо более продуктивными при обнаружении ошибок модуля.  


Zooba

+ 4 -
Мое мнение: если вы зависите от минимального / максимального / определенного размера, не просто предполагайте, что (скажем) unsigned int составляет 32 байта - используйте вместо этого uint32_t ( при условии, что ваш компилятор поддерживает C99).  


Ben Combee

+ 16 -
Я использую абстракцию типов очень редко. Вот мои аргументы, отсортированные в порядке возрастания субъективности: Локальные переменные отличаются от членов структуры и массивов в том смысле, что вы хотите, чтобы они помещались в регистр. На цели 32b / 64b локальный int16_t может сделать код медленнее по сравнению с локальным int, поскольку компилятору придется добавлять операции в / force / overflow в соответствии с семантикой int16_t. В то время как C99 определяет typedef intfast_t, AFAIK простое int также будет вписываться в регистр, и это, безусловно, более короткое имя. Организации, которым нравятся эти определения типов, почти всегда заканчиваются несколькими из них (INT32, int32_t, INT32_T, до бесконечности). Таким образом, организациям, использующим встроенные типы, лучше иметь только один набор имен. Я хотел бы, чтобы люди использовали typedefs из stdint.h или windows.h или чего-либо существующего; и когда у цели нет этого файла .h, насколько сложно его добавить? Определение типа теоретически может помочь переносимости, но я, например, никогда ничего от них не получил. Есть ли полезная система, которую вы можете портировать с цели 32b на 16b? Есть ли система 16b, которая не является тривиальной для портирования на 32b цели? Более того, если большинство переменных являются целочисленными, вы на самом деле получите что-то от 32-битной новой цели, но если они являются int16_t, вы этого не сделаете. А места, которые трудно переносить, все равно требуют ручного осмотра; прежде чем попробовать порт, вы не знаете, где они находятся. Теперь, если кто-то думает, что так легко портировать вещи, если у вас повсюду есть typedefs - когда приходит время к порту, что случается с несколькими системами, напишите скрипт, преобразующий все имена в базе кода. Это должно работать в соответствии с логикой, не требующей ручной проверки, и откладывает усилия до момента, когда это действительно приносит пользу. Теперь, если переносимость может быть теоретическим преимуществом typedefs, читабельность наверняка пойдет на спад. Просто посмотрите на stdint.h: {int,uint}{max,fast,least}{8,16,32,64}_t. Много типов. Программа имеет много переменных; действительно ли так легко понять, какой должен быть int_fast16_t, а какой должен быть uint_least32_t? Сколько раз мы молча обращаемся между ними, делая их совершенно бессмысленными? (Мне особенно нравятся преобразования BOOL / Bool / eBool / boolean / bool / int. Каждая программа, написанная упорядоченной организацией, предписывающей typedefs, усеяна этим). Конечно, в C ++ мы могли бы сделать систему типов более строгой, заключив числа в экземпляры класса шаблона в перегруженные операторы и прочее. Это означает, что теперь вы получите сообщения об ошибках класса формы Number без оператора + перегрузка для аргумента типа класса Number, кандидаты ... Я не называю эту читабельность, либо. Ваши шансы на правильную реализацию этих классов-оберток невелики, и большую часть времени вы будете ждать, пока не скомпилируются бесчисленные экземпляры шаблонов.


Bernard

+ 1 -
Мне нравится использовать типы stdint.h для определения системных API, в частности, потому что они явно говорят о том, каковы большие элементы. В прежние времена Palm OS системные API-интерфейсы определялись с использованием множества «лишенных смысла» типов, таких как Word и SWord, которые были унаследованы от очень классической Mac OS. Вместо этого они произвели очистку, чтобы сказать Int16, и это облегчило понимание API для новичков, особенно в связи со странными проблемами с 16-разрядными указателями в этой системе. Когда они разрабатывали Palm OS Cobalt, они снова изменили эти имена в соответствии с именами stdint.h, что сделало его еще более понятным и уменьшило количество typedef, которыми они должны были управлять.  


Chris Hanson

+ 7 -
Я считаю, что стандарты MISRA предлагают (требуют?) использование typedefs. С личной точки зрения, использование typedefs не оставляет путаницы относительно размера (в битах / байтах) определенных типов. Я видел, как ведущие разработчики пытаются использовать оба способа разработки, используя стандартные типы, например int и использование пользовательских типов, например UInt32. Если код не переносимый, то использование typedefs не принесет особой пользы, однако, если вы, как и я, работаете с обоими типами программного обеспечения (переносное и фиксированное окружение), то может быть полезно придерживаться стандарта и использовать обрезанные типы. По крайней мере, как вы говорите, программист тогда очень хорошо знает, сколько памяти они используют. Другой фактор, который следует учитывать, - насколько вы уверены, что код не будет перенесен в другую среду? Я видел, что код, специфичный для процессора, нужно переводить, так как аппаратный инженер внезапно должен был сменить плату, это не очень хорошая ситуация, но из-за пользовательских typedefs это могло быть намного хуже!


Теги

c | embedded